Browse Source

role et excel mis a jours

31052025_01
b.razafimandimbihery 6 months ago
parent
commit
34569c2843
  1. 509
      lib/Components/appDrawer.dart
  2. 21
      lib/Views/loginPage.dart
  3. 123
      lib/controller/userController.dart

509
lib/Components/appDrawer.dart

@ -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();
}
},
); );
} }
} }

21
lib/Views/loginPage.dart

@ -63,13 +63,13 @@ class _LoginPageState extends State<LoginPage> {
super.dispose(); super.dispose();
} }
Future<void> saveUser(String username, String role, int userId) async { Future<void> saveUserData(Users user, String role, int userId) async {
try { try {
final prefs = await SharedPreferences.getInstance(); // CORRECTION : Utiliser la nouvelle méthode du contrôleur
await prefs.setString('username', username); // Le contrôleur se charge maintenant de tout (observable + SharedPreferences)
await prefs.setString('role', role); userController.setUserWithCredentials(user, role, userId);
await prefs.setInt('user_id', userId);
print('Utilisateur sauvegardé: $username, rôle: $role, id: $userId'); print('Utilisateur sauvegardé: ${user.username}, rôle: $role, id: $userId');
} catch (error) { } catch (error) {
print('Erreur lors de la sauvegarde: $error'); print('Erreur lors de la sauvegarde: $error');
throw Exception('Erreur lors de la sauvegarde des données utilisateur'); throw Exception('Erreur lors de la sauvegarde des données utilisateur');
@ -128,12 +128,9 @@ class _LoginPageState extends State<LoginPage> {
print('Rôle: ${userCredentials['role']}'); print('Rôle: ${userCredentials['role']}');
print('ID: ${userCredentials['id']}'); print('ID: ${userCredentials['id']}');
// Sauvegarder dans le contrôleur // CORRECTION : Sauvegarder ET mettre à jour le contrôleur
// userController.setUser(user); await saveUserData(
user,
// Sauvegarder dans SharedPreferences
await saveUser(
userCredentials['username'] as String,
userCredentials['role'] as String, userCredentials['role'] as String,
userCredentials['id'] as int, userCredentials['id'] as int,
); );

123
lib/controller/userController.dart

@ -10,6 +10,7 @@ class UserController extends GetxController {
final _name = ''.obs; final _name = ''.obs;
final _lastname = ''.obs; final _lastname = ''.obs;
final _password = ''.obs; final _password = ''.obs;
final _userId = 0.obs; // Ajout de l'ID utilisateur
String get username => _username.value; String get username => _username.value;
String get email => _email.value; String get email => _email.value;
@ -17,6 +18,7 @@ class UserController extends GetxController {
String get name => _name.value; String get name => _name.value;
String get lastname => _lastname.value; String get lastname => _lastname.value;
String get password => _password.value; String get password => _password.value;
int get userId => _userId.value;
@override @override
void onInit() { void onInit() {
@ -24,43 +26,90 @@ class UserController extends GetxController {
loadUserData(); // Charger les données au démarrage loadUserData(); // Charger les données au démarrage
} }
// Charger les données depuis SharedPreferences // CORRECTION : Charger les données complètes depuis SharedPreferences ET la base de données
Future<void> loadUserData() async { Future<void> loadUserData() async {
try { try {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
_username.value = prefs.getString('username') ?? ''; final storedUsername = prefs.getString('username') ?? '';
_email.value = prefs.getString('email') ?? ''; final storedRole = prefs.getString('role') ?? '';
_role.value = prefs.getString('role') ?? ''; final storedUserId = prefs.getInt('user_id') ?? 0;
_name.value = prefs.getString('name') ?? '';
_lastname.value = prefs.getString('lastname') ?? '';
print("Données chargées - Username: ${_username.value}"); if (storedUsername.isNotEmpty) {
print("Role: ${_role.value}"); try {
// Récupérer les données complètes depuis la base de données
Users user = await AppDatabase.instance.getUser(storedUsername);
// Mettre à jour TOUTES les données
_username.value = user.username;
_email.value = user.email;
_name.value = user.name;
_lastname.value = user.lastName;
_password.value = user.password;
_role.value = storedRole; // Récupéré depuis SharedPreferences
_userId.value = storedUserId; // Récupéré depuis SharedPreferences
print("✅ Données chargées depuis la DB - Username: ${_username.value}");
print("✅ Name: ${_name.value}, Email: ${_email.value}");
print("✅ Role: ${_role.value}, UserID: ${_userId.value}");
} catch (dbError) {
print('❌ Erreur DB, chargement depuis SharedPreferences uniquement: $dbError');
// Fallback : charger depuis SharedPreferences uniquement
_username.value = storedUsername;
_email.value = prefs.getString('email') ?? '';
_role.value = storedRole;
_name.value = prefs.getString('name') ?? '';
_lastname.value = prefs.getString('lastname') ?? '';
_userId.value = storedUserId;
}
} else {
print("❌ Aucun utilisateur stocké trouvé");
}
} catch (e) { } catch (e) {
print('Erreur lors du chargement des données utilisateur: $e'); print('Erreur lors du chargement des données utilisateur: $e');
} }
} }
// NOUVELLE MÉTHODE : Mise à jour complète avec Users + credentials
void setUserWithCredentials(Users user, String role, int userId) {
_username.value = user.username;
_email.value = user.email;
_role.value = role; // Rôle depuis les credentials
_name.value = user.name;
_lastname.value = user.lastName;
_password.value = user.password;
_userId.value = userId; // ID depuis les credentials
print("✅ Utilisateur mis à jour avec credentials:");
print(" Username: ${_username.value}");
print(" Name: ${_name.value}");
print(" Email: ${_email.value}");
print(" Role: ${_role.value}");
print(" UserID: ${_userId.value}");
// Sauvegarder dans SharedPreferences
saveUserData();
}
// MÉTHODE EXISTANTE AMÉLIORÉE
void setUser(Users user) { void setUser(Users user) {
_username.value = user.username; _username.value = user.username;
print("username " + _username.value);
_email.value = user.email; _email.value = user.email;
print(_email.value);
_role.value = user.role; _role.value = user.role;
print(_role.value);
_name.value = user.name; _name.value = user.name;
print(_name.value);
_lastname.value = user.lastName; _lastname.value = user.lastName;
print(_lastname.value);
_password.value = user.password; _password.value = user.password;
print(_password.value); // Note: _userId reste inchangé si pas fourni
print("✅ Utilisateur mis à jour (méthode legacy):");
print(" Username: ${_username.value}");
print(" Role: ${_role.value}");
// Sauvegarder dans SharedPreferences // Sauvegarder dans SharedPreferences
saveUserData(); saveUserData();
} }
// Sauvegarder les données dans SharedPreferences // CORRECTION : Sauvegarder TOUTES les données importantes
Future<void> saveUserData() async { Future<void> saveUserData() async {
try { try {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
@ -70,23 +119,26 @@ class UserController extends GetxController {
await prefs.setString('role', _role.value); await prefs.setString('role', _role.value);
await prefs.setString('name', _name.value); await prefs.setString('name', _name.value);
await prefs.setString('lastname', _lastname.value); await prefs.setString('lastname', _lastname.value);
await prefs.setInt('user_id', _userId.value); // Sauvegarder l'ID
print("Données sauvegardées avec succès"); print("Données sauvegardées avec succès dans SharedPreferences");
} catch (e) { } catch (e) {
print('Erreur lors de la sauvegarde des données utilisateur: $e'); print('Erreur lors de la sauvegarde des données utilisateur: $e');
} }
} }
// Méthode pour vider les données utilisateur // CORRECTION : Vider TOUTES les données (SharedPreferences + Observables)
Future<void> clearUserData() async { Future<void> clearUserData() async {
try { try {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
// Vider SharedPreferences
await prefs.remove('username'); await prefs.remove('username');
await prefs.remove('email'); await prefs.remove('email');
await prefs.remove('role'); await prefs.remove('role');
await prefs.remove('name'); await prefs.remove('name');
await prefs.remove('lastname'); await prefs.remove('lastname');
await prefs.remove('user_id'); // Supprimer l'ID aussi
// Vider les variables observables // Vider les variables observables
_username.value = ''; _username.value = '';
@ -95,23 +147,35 @@ class UserController extends GetxController {
_name.value = ''; _name.value = '';
_lastname.value = ''; _lastname.value = '';
_password.value = ''; _password.value = '';
_userId.value = 0; // Réinitialiser l'ID
print("Données utilisateur effacées"); print("✅ Toutes les données utilisateur ont été effacées");
} catch (e) { } catch (e) {
print('Erreur lors de l\'effacement des données utilisateur: $e'); print('Erreur lors de l\'effacement des données utilisateur: $e');
} }
} }
// MÉTHODE UTILITAIRE : Vérifier si un utilisateur est connecté
bool get isLoggedIn => _username.value.isNotEmpty && _userId.value > 0;
// MÉTHODE UTILITAIRE : Obtenir le nom complet
String get fullName => '${_name.value} ${_lastname.value}'.trim();
Future<bool> hasPermission(String permission, String route) async { Future<bool> hasPermission(String permission, String route) async {
try { try {
if (_username.value.isEmpty) { if (_username.value.isEmpty) {
print('Username vide, rechargement des données...'); print('⚠️ Username vide, rechargement des données...');
await loadUserData(); await loadUserData();
} }
if (_username.value.isEmpty) {
print('❌ Impossible de vérifier les permissions : utilisateur non connecté');
return false;
}
return await AppDatabase.instance.hasPermission(username, permission, route); return await AppDatabase.instance.hasPermission(username, permission, route);
} catch (e) { } catch (e) {
print('Erreur vérification permission: $e'); print('Erreur vérification permission: $e');
return false; // Sécurité : refuser l'accès en cas d'erreur return false; // Sécurité : refuser l'accès en cas d'erreur
} }
} }
@ -124,4 +188,17 @@ class UserController extends GetxController {
} }
return false; return false;
} }
// MÉTHODE DEBUG : Afficher l'état actuel
void debugPrintUserState() {
print("=== ÉTAT UTILISATEUR ===");
print("Username: ${_username.value}");
print("Name: ${_name.value}");
print("Lastname: ${_lastname.value}");
print("Email: ${_email.value}");
print("Role: ${_role.value}");
print("UserID: ${_userId.value}");
print("IsLoggedIn: $isLoggedIn");
print("========================");
}
} }
Loading…
Cancel
Save