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(); 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 drawerItems.add(
_buildDrawerItem( await _buildDrawerItem(
icon: Icons.home, icon: Icons.home,
title: "Accueil", title: "Accueil",
color: Colors.blue, color: Colors.blue,
permissionAction: 'view', permissionAction: 'view',
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), icon: Icons.person_add,
child: Text( title: "Ajouter un utilisateur",
"GESTION UTILISATEURS", color: Colors.green,
style: TextStyle( permissionAction: 'create',
color: Colors.grey, permissionRoute: '/ajouter-utilisateur',
fontSize: 12, onTap: () => Get.to(const RegistrationPage()),
fontWeight: FontWeight.bold, ),
), 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',
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()),
),
// Section Produits List<Widget> gestionProduitsItems = [
const Padding( await _buildDrawerItem(
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), icon: Icons.inventory,
child: Text( title: "Gestion des produits",
"GESTION PRODUITS", color: Colors.indigoAccent,
style: TextStyle( permissionAction: 'create',
color: Colors.grey, permissionRoute: '/ajouter-produit',
fontSize: 12, onTap: () => Get.to(const ProductManagementPage()),
fontWeight: FontWeight.bold, ),
), 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", drawerItems.addAll(gestionProduitsItems);
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()),
),
// Section Commandes List<Widget> gestionCommandesItems = [
const Padding( await _buildDrawerItem(
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), icon: Icons.add_shopping_cart,
child: Text( title: "Nouvelle commande",
"GESTION COMMANDES", color: Colors.orange,
style: TextStyle( permissionAction: 'create',
color: Colors.grey, permissionRoute: '/nouvelle-commande',
fontSize: 12, onTap: () => Get.to(const NouvelleCommandePage()),
fontWeight: FontWeight.bold, ),
), 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", drawerItems.addAll(gestionCommandesItems);
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()),
),
// Section Rapports List<Widget> rapportsItems = [
const Padding( await _buildDrawerItem(
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), icon: Icons.bar_chart,
child: Text( title: "Bilan mensuel",
"RAPPORTS", color: Colors.teal,
style: TextStyle( permissionAction: 'read',
color: Colors.grey, permissionRoute: '/bilan',
fontSize: 12, onTap: () => Get.to(const BilanMois()),
fontWeight: FontWeight.bold, ),
), 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", drawerItems.addAll(rapportsItems);
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()),
),
// Section Administration List<Widget> administrationItems = [
const Padding( await _buildDrawerItem(
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), icon: Icons.admin_panel_settings,
child: Text( title: "Gérer les rôles",
"ADMINISTRATION", color: Colors.redAccent,
style: TextStyle( permissionAction: 'admin',
color: Colors.grey, permissionRoute: '/gerer-roles',
fontSize: 12, onTap: () => Get.to(const RoleListPage()),
fontWeight: FontWeight.bold, ),
), ];
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", drawerItems.addAll(administrationItems);
color: Colors.redAccent, }
permissionAction: 'admin',
permissionRoute: '/gerer-roles', drawerItems.add(const Divider());
onTap: () => Get.to(const RoleListPage()),
),
// Déconnexion drawerItems.add(
const Divider(), ListTile(
_buildDrawerItem( leading: const Icon(Icons.logout, color: Colors.red),
icon: Icons.logout, title: const Text("Déconnexion"),
onTap: () {
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,
); );

125
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') ?? ''; if (storedUsername.isNotEmpty) {
try {
print("Données chargées - Username: ${_username.value}"); // Récupérer les données complètes depuis la base de données
print("Role: ${_role.value}"); 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