Browse Source

role et excel mis a jours

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

189
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,10 +32,26 @@ 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(
future: _buildDrawerItems(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return ListView(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
children: [ children: snapshot.data as List<Widget>,
// Header avec informations utilisateur );
} else {
return const Center(child: CircularProgressIndicator());
}
},
),
);
}
Future<List<Widget>> _buildDrawerItems() async {
List<Widget> drawerItems = [];
drawerItems.add(
GetBuilder<UserController>( GetBuilder<UserController>(
builder: (controller) => Container( builder: (controller) => Container(
padding: const EdgeInsets.only(top: 50, left: 20, bottom: 20), padding: const EdgeInsets.only(top: 50, left: 20, bottom: 20),
@ -54,7 +73,7 @@ class CustomDrawer extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
controller.name, controller.name.isNotEmpty ? controller.name : 'Utilisateur',
style: const TextStyle( style: const TextStyle(
color: Colors.white, color: Colors.white,
fontSize: 18, fontSize: 18,
@ -62,14 +81,7 @@ class CustomDrawer extends StatelessWidget {
), ),
), ),
Text( Text(
controller.email, controller.role.isNotEmpty ? controller.role : 'Aucun rôle',
style: const TextStyle(
color: Colors.white70,
fontSize: 14,
),
),
Text(
controller.role,
style: const TextStyle( style: const TextStyle(
color: Colors.white70, color: Colors.white70,
fontSize: 12, fontSize: 12,
@ -81,9 +93,10 @@ class CustomDrawer extends StatelessWidget {
), ),
), ),
), ),
);
// Section Accueil drawerItems.add(
_buildDrawerItem( await _buildDrawerItem(
icon: Icons.home, icon: Icons.home,
title: "Accueil", title: "Accueil",
color: Colors.blue, color: Colors.blue,
@ -91,20 +104,10 @@ class CustomDrawer extends StatelessWidget {
permissionRoute: '/accueil', permissionRoute: '/accueil',
onTap: () => Get.to(const AccueilPage()), onTap: () => Get.to(const AccueilPage()),
), ),
);
// Section Utilisateurs List<Widget> gestionUtilisateursItems = [
const Padding( await _buildDrawerItem(
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, icon: Icons.person_add,
title: "Ajouter un utilisateur", title: "Ajouter un utilisateur",
color: Colors.green, color: Colors.green,
@ -112,20 +115,22 @@ class CustomDrawer extends StatelessWidget {
permissionRoute: '/ajouter-utilisateur', permissionRoute: '/ajouter-utilisateur',
onTap: () => Get.to(const RegistrationPage()), onTap: () => Get.to(const RegistrationPage()),
), ),
_buildDrawerItem( await _buildDrawerItem(
icon: Icons.supervised_user_circle, icon: Icons.supervised_user_circle,
title: "Gérer les utilisateurs", title: "Gérer les utilisateurs",
color: Color.fromARGB(255, 4, 54, 95), color: const Color.fromARGB(255, 4, 54, 95),
permissionAction: 'update', permissionAction: 'update',
permissionRoute: '/modifier-utilisateur', permissionRoute: '/modifier-utilisateur',
onTap: () => Get.to(const ListUserPage()), onTap: () => Get.to(const ListUserPage()),
), ),
];
// Section Produits if (gestionUtilisateursItems.any((item) => item is ListTile)) {
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(
"GESTION PRODUITS", "GESTION UTILISATEURS",
style: TextStyle( style: TextStyle(
color: Colors.grey, color: Colors.grey,
fontSize: 12, fontSize: 12,
@ -133,7 +138,12 @@ class CustomDrawer extends StatelessWidget {
), ),
), ),
), ),
_buildDrawerItem( );
drawerItems.addAll(gestionUtilisateursItems);
}
List<Widget> gestionProduitsItems = [
await _buildDrawerItem(
icon: Icons.inventory, icon: Icons.inventory,
title: "Gestion des produits", title: "Gestion des produits",
color: Colors.indigoAccent, color: Colors.indigoAccent,
@ -141,7 +151,7 @@ class CustomDrawer extends StatelessWidget {
permissionRoute: '/ajouter-produit', permissionRoute: '/ajouter-produit',
onTap: () => Get.to(const ProductManagementPage()), onTap: () => Get.to(const ProductManagementPage()),
), ),
_buildDrawerItem( await _buildDrawerItem(
icon: Icons.storage, icon: Icons.storage,
title: "Gestion de stock", title: "Gestion de stock",
color: Colors.blueAccent, color: Colors.blueAccent,
@ -149,12 +159,14 @@ class CustomDrawer extends StatelessWidget {
permissionRoute: '/gestion-stock', permissionRoute: '/gestion-stock',
onTap: () => Get.to(const GestionStockPage()), onTap: () => Get.to(const GestionStockPage()),
), ),
];
// Section Commandes if (gestionProduitsItems.any((item) => item is ListTile)) {
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(
"GESTION COMMANDES", "GESTION PRODUITS",
style: TextStyle( style: TextStyle(
color: Colors.grey, color: Colors.grey,
fontSize: 12, fontSize: 12,
@ -162,7 +174,12 @@ class CustomDrawer extends StatelessWidget {
), ),
), ),
), ),
_buildDrawerItem( );
drawerItems.addAll(gestionProduitsItems);
}
List<Widget> gestionCommandesItems = [
await _buildDrawerItem(
icon: Icons.add_shopping_cart, icon: Icons.add_shopping_cart,
title: "Nouvelle commande", title: "Nouvelle commande",
color: Colors.orange, color: Colors.orange,
@ -170,7 +187,7 @@ class CustomDrawer extends StatelessWidget {
permissionRoute: '/nouvelle-commande', permissionRoute: '/nouvelle-commande',
onTap: () => Get.to(const NouvelleCommandePage()), onTap: () => Get.to(const NouvelleCommandePage()),
), ),
_buildDrawerItem( await _buildDrawerItem(
icon: Icons.list_alt, icon: Icons.list_alt,
title: "Gérer les commandes", title: "Gérer les commandes",
color: Colors.deepPurple, color: Colors.deepPurple,
@ -178,12 +195,14 @@ class CustomDrawer extends StatelessWidget {
permissionRoute: '/gerer-commandes', permissionRoute: '/gerer-commandes',
onTap: () => Get.to(const GestionCommandesPage()), onTap: () => Get.to(const GestionCommandesPage()),
), ),
];
// Section Rapports if (gestionCommandesItems.any((item) => item is ListTile)) {
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(
"RAPPORTS", "GESTION COMMANDES",
style: TextStyle( style: TextStyle(
color: Colors.grey, color: Colors.grey,
fontSize: 12, fontSize: 12,
@ -191,7 +210,12 @@ class CustomDrawer extends StatelessWidget {
), ),
), ),
), ),
_buildDrawerItem( );
drawerItems.addAll(gestionCommandesItems);
}
List<Widget> rapportsItems = [
await _buildDrawerItem(
icon: Icons.bar_chart, icon: Icons.bar_chart,
title: "Bilan mensuel", title: "Bilan mensuel",
color: Colors.teal, color: Colors.teal,
@ -199,7 +223,7 @@ class CustomDrawer extends StatelessWidget {
permissionRoute: '/bilan', permissionRoute: '/bilan',
onTap: () => Get.to(const BilanMois()), onTap: () => Get.to(const BilanMois()),
), ),
_buildDrawerItem( await _buildDrawerItem(
icon: Icons.history, icon: Icons.history,
title: "Historique", title: "Historique",
color: Colors.blue, color: Colors.blue,
@ -207,12 +231,14 @@ class CustomDrawer extends StatelessWidget {
permissionRoute: '/historique', permissionRoute: '/historique',
onTap: () => Get.to(HistoryPage()), onTap: () => Get.to(HistoryPage()),
), ),
];
// Section Administration if (rapportsItems.any((item) => item is ListTile)) {
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", "RAPPORTS",
style: TextStyle( style: TextStyle(
color: Colors.grey, color: Colors.grey,
fontSize: 12, fontSize: 12,
@ -220,7 +246,12 @@ class CustomDrawer extends StatelessWidget {
), ),
), ),
), ),
_buildDrawerItem( );
drawerItems.addAll(rapportsItems);
}
List<Widget> administrationItems = [
await _buildDrawerItem(
icon: Icons.admin_panel_settings, icon: Icons.admin_panel_settings,
title: "Gérer les rôles", title: "Gérer les rôles",
color: Colors.redAccent, color: Colors.redAccent,
@ -228,13 +259,31 @@ class CustomDrawer extends StatelessWidget {
permissionRoute: '/gerer-roles', permissionRoute: '/gerer-roles',
onTap: () => Get.to(const RoleListPage()), onTap: () => Get.to(const RoleListPage()),
), ),
];
// Déconnexion if (administrationItems.any((item) => item is ListTile)) {
const Divider(), drawerItems.add(
_buildDrawerItem( const Padding(
icon: Icons.logout, padding: EdgeInsets.only(left: 20, top: 15, bottom: 5),
title: "Déconnexion", child: Text(
color: Colors.red, "ADMINISTRATION",
style: TextStyle(
color: Colors.grey,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
),
);
drawerItems.addAll(administrationItems);
}
drawerItems.add(const Divider());
drawerItems.add(
ListTile(
leading: const Icon(Icons.logout, color: Colors.red),
title: const Text("Déconnexion"),
onTap: () { onTap: () {
Get.defaultDialog( Get.defaultDialog(
title: "Déconnexion", title: "Déconnexion",
@ -249,8 +298,8 @@ class CustomDrawer extends StatelessWidget {
backgroundColor: Colors.red, backgroundColor: Colors.red,
), ),
child: const Text("Oui"), child: const Text("Oui"),
onPressed: () { onPressed: () async {
clearUserData(); await clearUserData();
Get.offAll(const LoginPage()); Get.offAll(const LoginPage());
}, },
), ),
@ -258,45 +307,33 @@ class CustomDrawer extends StatelessWidget {
); );
}, },
), ),
],
),
); );
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,
); );

119
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') ?? '';
final storedRole = prefs.getString('role') ?? '';
final storedUserId = prefs.getInt('user_id') ?? 0;
if (storedUsername.isNotEmpty) {
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') ?? ''; _email.value = prefs.getString('email') ?? '';
_role.value = prefs.getString('role') ?? ''; _role.value = storedRole;
_name.value = prefs.getString('name') ?? ''; _name.value = prefs.getString('name') ?? '';
_lastname.value = prefs.getString('lastname') ?? ''; _lastname.value = prefs.getString('lastname') ?? '';
_userId.value = storedUserId;
print("Données chargées - Username: ${_username.value}"); }
print("Role: ${_role.value}"); } 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