Browse Source

role et excel mis a jours

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

491
lib/Components/appDrawer.dart

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

21
lib/Views/loginPage.dart

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

125
lib/controller/userController.dart

@ -10,6 +10,7 @@ class UserController extends GetxController {
final _name = ''.obs;
final _lastname = ''.obs;
final _password = ''.obs;
final _userId = 0.obs; // Ajout de l'ID utilisateur
String get username => _username.value;
String get email => _email.value;
@ -17,6 +18,7 @@ class UserController extends GetxController {
String get name => _name.value;
String get lastname => _lastname.value;
String get password => _password.value;
int get userId => _userId.value;
@override
void onInit() {
@ -24,43 +26,90 @@ class UserController extends GetxController {
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 {
try {
final prefs = await SharedPreferences.getInstance();
_username.value = prefs.getString('username') ?? '';
_email.value = prefs.getString('email') ?? '';
_role.value = prefs.getString('role') ?? '';
_name.value = prefs.getString('name') ?? '';
_lastname.value = prefs.getString('lastname') ?? '';
print("Données chargées - Username: ${_username.value}");
print("Role: ${_role.value}");
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') ?? '';
_role.value = storedRole;
_name.value = prefs.getString('name') ?? '';
_lastname.value = prefs.getString('lastname') ?? '';
_userId.value = storedUserId;
}
} else {
print("❌ Aucun utilisateur stocké trouvé");
}
} 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) {
_username.value = user.username;
print("username " + _username.value);
_email.value = user.email;
print(_email.value);
_role.value = user.role;
print(_role.value);
_name.value = user.name;
print(_name.value);
_lastname.value = user.lastName;
print(_lastname.value);
_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
saveUserData();
}
// Sauvegarder les données dans SharedPreferences
// CORRECTION : Sauvegarder TOUTES les données importantes
Future<void> saveUserData() async {
try {
final prefs = await SharedPreferences.getInstance();
@ -70,23 +119,26 @@ class UserController extends GetxController {
await prefs.setString('role', _role.value);
await prefs.setString('name', _name.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) {
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 {
try {
final prefs = await SharedPreferences.getInstance();
// Vider SharedPreferences
await prefs.remove('username');
await prefs.remove('email');
await prefs.remove('role');
await prefs.remove('name');
await prefs.remove('lastname');
await prefs.remove('user_id'); // Supprimer l'ID aussi
// Vider les variables observables
_username.value = '';
@ -95,23 +147,35 @@ class UserController extends GetxController {
_name.value = '';
_lastname.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) {
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 {
try {
if (_username.value.isEmpty) {
print('Username vide, rechargement des données...');
print('⚠️ Username vide, rechargement des données...');
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);
} 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
}
}
@ -124,4 +188,17 @@ class UserController extends GetxController {
}
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