import 'package:flutter/material.dart'; import 'package:youmazgestion/Components/app_bar.dart'; import 'package:youmazgestion/Models/Permission.dart'; //import 'package:youmazgestion/Services/app_database.dart'; import 'package:youmazgestion/Models/role.dart'; import 'package:youmazgestion/Services/stock_managementDatabase.dart'; class HandleUserRole extends StatefulWidget { const HandleUserRole({super.key}); @override State createState() => _HandleUserRoleState(); } class _HandleUserRoleState extends State { final db = AppDatabase.instance; List roles = []; List permissions = []; List> menus = []; Map>> roleMenuPermissionsMap = {}; final TextEditingController _roleController = TextEditingController(); @override void initState() { super.initState(); _initData(); } Future _initData() async { try { final roleList = await db.getRoles(); final perms = await db.getAllPermissions(); // Récupération mise à jour des menus avec gestion d'erreur final menuList = await db.getAllMenus(); Map>> tempRoleMenuPermissionsMap = {}; for (var role in roleList) { final roleId = role.id!; tempRoleMenuPermissionsMap[roleId] = {}; for (var menu in menuList) { final menuId = menu['id'] as int; final menuPerms = await db.getPermissionsForRoleAndMenu(roleId, menuId); tempRoleMenuPermissionsMap[roleId]![menuId] = { for (var perm in perms) perm.name: menuPerms.any((mp) => mp.name == perm.name) }; } } setState(() { roles = roleList; permissions = perms; menus = menuList; roleMenuPermissionsMap = tempRoleMenuPermissionsMap; }); } catch (e) { print("Erreur lors de l'initialisation des données: $e"); // Afficher un message d'erreur à l'utilisateur ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Erreur lors du chargement des données: $e'), backgroundColor: Colors.red, ), ); } } Future _addRole() async { String designation = _roleController.text.trim(); if (designation.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Veuillez saisir une désignation pour le rôle'), backgroundColor: Colors.orange, ), ); return; } try { // Vérifier si le rôle existe déjà final existingRoles = roles.where((r) => r.designation.toLowerCase() == designation.toLowerCase()); if (existingRoles.isNotEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Ce rôle existe déjà'), backgroundColor: Colors.orange, ), ); return; } await db.createRole(Role(designation: designation)); _roleController.clear(); await _initData(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Rôle "$designation" créé avec succès'), backgroundColor: Colors.green, ), ); } catch (e) { print("Erreur lors de la création du rôle: $e"); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Erreur lors de la création du rôle: $e'), backgroundColor: Colors.red, ), ); } } Future _onPermissionToggle(int roleId, int menuId, String permission, bool enabled) async { try { final perm = permissions.firstWhere((p) => p.name == permission); if (enabled) { await db.assignRoleMenuPermission(roleId, menuId, perm.id!); } else { await db.removeRoleMenuPermission(roleId, menuId, perm.id!); } setState(() { roleMenuPermissionsMap[roleId]![menuId]![permission] = enabled; }); } catch (e) { print("Erreur lors de la modification de la permission: $e"); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Erreur lors de la modification de la permission: $e'), backgroundColor: Colors.red, ), ); } } Future _deleteRole(Role role) async { // Empêcher la suppression du Super Admin if (role.designation == 'Super Admin') { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Impossible de supprimer le rôle Super Admin'), backgroundColor: Colors.red, ), ); return; } // Demander confirmation final confirm = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Confirmer la suppression'), content: Text('Êtes-vous sûr de vouloir supprimer le rôle "${role.designation}" ?'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: const Text('Annuler'), ), TextButton( onPressed: () => Navigator.of(context).pop(true), style: TextButton.styleFrom(foregroundColor: Colors.red), child: const Text('Supprimer'), ), ], ), ); if (confirm == true) { try { await db.deleteRole(role.id); await _initData(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Rôle "${role.designation}" supprimé avec succès'), backgroundColor: Colors.green, ), ); } catch (e) { print("Erreur lors de la suppression du rôle: $e"); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Erreur lors de la suppression du rôle: $e'), backgroundColor: Colors.red, ), ); } } } @override Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar(title: "Gestion des rôles"), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ // Ajout de rôle Card( elevation: 6, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Row( children: [ Expanded( child: TextField( controller: _roleController, decoration: InputDecoration( labelText: 'Nouveau rôle', hintText: 'Ex: Manager, Vendeur...', border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), ), ), onSubmitted: (_) => _addRole(), ), ), const SizedBox(width: 10), ElevatedButton.icon( onPressed: _addRole, icon: const Icon(Icons.add), label: const Text('Ajouter'), style: ElevatedButton.styleFrom( backgroundColor: Colors.blue, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), ), ], ), ), ), const SizedBox(height: 20), // Affichage des statistiques if (roles.isNotEmpty) Card( elevation: 4, child: Padding( padding: const EdgeInsets.all(16.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _buildStatItem('Rôles', roles.length.toString(), Icons.people), _buildStatItem('Permissions', permissions.length.toString(), Icons.security), _buildStatItem('Menus', menus.length.toString(), Icons.menu), ], ), ), ), const SizedBox(height: 20), // Tableau des rôles et permissions if (roles.isNotEmpty && permissions.isNotEmpty && menus.isNotEmpty) Expanded( child: Card( elevation: 6, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), child: Padding( padding: const EdgeInsets.all(16.0), child: SingleChildScrollView( scrollDirection: Axis.vertical, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: menus.map((menu) { final menuId = menu['id'] as int; final menuName = menu['name'] as String; final menuRoute = menu['route'] as String; return Card( margin: const EdgeInsets.only(bottom: 16.0), elevation: 2, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: Colors.blue.shade50, borderRadius: BorderRadius.circular(8), ), child: Row( children: [ Icon(Icons.menu, color: Colors.blue.shade700), const SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( menuName, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, color: Colors.blue.shade700, ), ), Text( menuRoute, style: TextStyle( fontSize: 12, color: Colors.grey.shade600, ), ), ], ), ), ], ), ), const SizedBox(height: 12), SingleChildScrollView( scrollDirection: Axis.horizontal, child: DataTable( columnSpacing: 20, headingRowHeight: 50, dataRowHeight: 60, columns: [ const DataColumn( label: Text( 'Rôles', style: TextStyle(fontWeight: FontWeight.bold), ), ), ...permissions.map((perm) => DataColumn( label: Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.grey.shade100, borderRadius: BorderRadius.circular(4), ), child: Text( perm.name, style: const TextStyle(fontWeight: FontWeight.bold), ), ), )).toList(), const DataColumn( label: Text( 'Actions', style: TextStyle(fontWeight: FontWeight.bold), ), ), ], rows: roles.map((role) { final roleId = role.id!; return DataRow( cells: [ DataCell( Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: role.designation == 'Super Admin' ? Colors.red.shade50 : Colors.blue.shade50, borderRadius: BorderRadius.circular(4), ), child: Text( role.designation, style: TextStyle( fontWeight: FontWeight.w500, color: role.designation == 'Super Admin' ? Colors.red.shade700 : Colors.blue.shade700, ), ), ), ), ...permissions.map((perm) { final isChecked = roleMenuPermissionsMap[roleId]?[menuId]?[perm.name] ?? false; return DataCell( Checkbox( value: isChecked, onChanged: (bool? value) { _onPermissionToggle(roleId, menuId, perm.name, value ?? false); }, activeColor: Colors.green, ), ); }).toList(), DataCell( role.designation != 'Super Admin' ? IconButton( icon: Icon(Icons.delete, color: Colors.red.shade600), tooltip: 'Supprimer le rôle', onPressed: () => _deleteRole(role), ) : Icon(Icons.lock, color: Colors.grey.shade400), ), ], ); }).toList(), ), ), ], ), ), ); }).toList(), ), ), ), ), ) else Expanded( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.inbox, size: 64, color: Colors.grey.shade400), const SizedBox(height: 16), Text( 'Aucune donnée disponible', style: TextStyle( fontSize: 18, color: Colors.grey.shade600, fontWeight: FontWeight.w500, ), ), const SizedBox(height: 8), Text( 'Rôles: ${roles.length} | Permissions: ${permissions.length} | Menus: ${menus.length}', style: TextStyle( fontSize: 14, color: Colors.grey.shade500, ), ), const SizedBox(height: 16), ElevatedButton.icon( onPressed: _initData, icon: const Icon(Icons.refresh), label: const Text('Actualiser'), ), ], ), ), ), ], ), ), ); } Widget _buildStatItem(String label, String value, IconData icon) { return Column( children: [ Icon(icon, size: 32, color: Colors.blue.shade600), const SizedBox(height: 8), Text( value, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.black87, ), ), Text( label, style: TextStyle( fontSize: 14, color: Colors.grey.shade600, ), ), ], ); } @override void dispose() { _roleController.dispose(); super.dispose(); } }