Browse Source

qr code scanner

28062025_02
Stephane 5 months ago
parent
commit
b415b9f501
  1. 87
      lib/Components/appDrawer.dart
  2. 52
      lib/Views/demande_sortie_personnelle_page.dart
  3. 2
      lib/config/DatabaseConfig.dart
  4. 27
      lib/controller/HistoryController.dart
  5. 14
      lib/controller/userController.dart
  6. 24
      lib/main.dart

87
lib/Components/appDrawer.dart

@ -109,14 +109,15 @@ class CustomDrawer extends StatelessWidget {
});
} else {
invalidMenus.add(menu);
print("⚠️ Menu invalide ignoré dans CustomDrawer: id=$id, name='$name', route='$route'");
// print("⚠️ Menu invalide ignoré dans CustomDrawer: id=$id, name='$name', route='$route'");
}
}
// NOUVEAU: Ajouter le menu Demande Assignation pour Super Admin uniquement
if (userController.role == 'Super Admin') {
// Vérifier si le menu n'existe pas déjà
final bool demandeAssignationExists = validMenus.any((menu) => menu['route'] == '/demande-assignation');
final bool demandeAssignationExists =
validMenus.any((menu) => menu['route'] == '/demande-assignation');
if (!demandeAssignationExists) {
validMenus.add({
@ -124,7 +125,7 @@ class CustomDrawer extends StatelessWidget {
'name': 'Demande Assignation',
'route': '/demande-assignation',
});
print("✅ Menu 'Demande Assignation' ajouté pour Super Admin");
// print("✅ Menu 'Demande Assignation' ajouté pour Super Admin");
}
}
@ -133,7 +134,8 @@ class CustomDrawer extends StatelessWidget {
// Afficher les statistiques de validation
if (invalidMenus.isNotEmpty) {
print("📊 CustomDrawer: ${validMenus.length} menus valides, ${invalidMenus.length} invalides");
// print(
// "📊 CustomDrawer: ${validMenus.length} menus valides, ${invalidMenus.length} invalides");
}
if (validMenus.isEmpty) {
@ -158,7 +160,8 @@ class CustomDrawer extends StatelessWidget {
final deduplicatedMenus = uniqueMenus.values.toList();
if (deduplicatedMenus.length != validMenus.length) {
print("🔧 CustomDrawer: ${validMenus.length - deduplicatedMenus.length} doublons supprimés");
// print(
// "🔧 CustomDrawer: ${validMenus.length - deduplicatedMenus.length} doublons supprimés");
}
// Organiser les menus par catégories
@ -173,7 +176,9 @@ class CustomDrawer extends StatelessWidget {
};
// Accueil toujours en premier
final accueilMenu = deduplicatedMenus.where((menu) => menu['route'] == '/accueil').firstOrNull;
final accueilMenu = deduplicatedMenus
.where((menu) => menu['route'] == '/accueil')
.firstOrNull;
if (accueilMenu != null) {
drawerItems.add(_buildDrawerItemFromMenu(accueilMenu));
}
@ -184,7 +189,7 @@ class CustomDrawer extends StatelessWidget {
// Validation supplémentaire avant categorisation
if (route.isEmpty) {
print("⚠️ Route vide ignorée: ${menu['name']}");
// print("⚠️ Route vide ignorée: ${menu['name']}");
continue;
}
@ -224,7 +229,7 @@ class CustomDrawer extends StatelessWidget {
break;
default:
// Menu non catégorisé
print("⚠️ Menu non catégorisé: $route");
// print("⚠️ Menu non catégorisé: $route");
break;
}
}
@ -233,7 +238,8 @@ class CustomDrawer extends StatelessWidget {
categorizedMenus.forEach((categoryName, menus) {
if (menus.isNotEmpty) {
// Afficher la catégorie SUPER ADMIN seulement pour les Super Admin
if (categoryName == 'SUPER ADMIN' && userController.role != 'Super Admin') {
if (categoryName == 'SUPER ADMIN' &&
userController.role != 'Super Admin') {
return; // Skip cette catégorie
}
@ -250,37 +256,42 @@ class CustomDrawer extends StatelessWidget {
/// NOUVEAU: Méthode pour ajouter les menus de sorties personnelles
void _addSortiesPersonnellesMenus(List<Map<String, dynamic>> validMenus) {
// Menu Demande Sortie Personnelle - Accessible à tous les utilisateurs connectés
final bool demandeSortieExists = validMenus.any((menu) => menu['route'] == '/demande-sortie-personnelle');
final bool demandeSortieExists = validMenus
.any((menu) => menu['route'] == '/demande-sortie-personnelle');
if (!demandeSortieExists) {
validMenus.add({
'id': 'demande_sortie_personnelle',
'name': 'Demande sortie personnelle',
'route': '/demande-sortie-personnelle',
});
print("✅ Menu 'Demande sortie personnelle' ajouté pour tous les utilisateurs");
// print(
// "✅ Menu 'Demande sortie personnelle' ajouté pour tous les utilisateurs");
}
// Menu Historique Sorties Personnelles - Accessible à tous les utilisateurs connectés
final bool historiqueSortiesExists = validMenus.any((menu) => menu['route'] == '/historique-sorties-personnelles');
final bool historiqueSortiesExists = validMenus
.any((menu) => menu['route'] == '/historique-sorties-personnelles');
if (!historiqueSortiesExists) {
validMenus.add({
'id': 'historique_sorties_personnelles',
'name': 'Historique sorties personnelles',
'route': '/historique-sorties-personnelles',
});
print("✅ Menu 'Historique sorties personnelles' ajouté pour tous les utilisateurs");
// print(
// "✅ Menu 'Historique sorties personnelles' ajouté pour tous les utilisateurs");
}
// Menu Approbation Sorties - Accessible SEULEMENT aux Super Admin
if (userController.role == 'Super Admin') {
final bool approbationSortiesExists = validMenus.any((menu) => menu['route'] == '/approbation-sorties');
final bool approbationSortiesExists =
validMenus.any((menu) => menu['route'] == '/approbation-sorties');
if (!approbationSortiesExists) {
validMenus.add({
'id': 'approbation_sorties',
'name': 'Approuver sorties',
'route': '/approbation-sorties',
});
print("✅ Menu 'Approuver sorties' ajouté pour Super Admin");
// print("✅ Menu 'Approuver sorties' ajouté pour Super Admin");
}
}
}
@ -292,7 +303,8 @@ class CustomDrawer extends StatelessWidget {
final routeObj = menu['route'];
if (nameObj == null || routeObj == null) {
print("⚠️ Menu invalide dans _buildDrawerItemFromMenu: name=$nameObj, route=$routeObj");
// print(
// "⚠️ Menu invalide dans _buildDrawerItemFromMenu: name=$nameObj, route=$routeObj");
return const SizedBox.shrink();
}
@ -300,7 +312,7 @@ class CustomDrawer extends StatelessWidget {
final String route = routeObj.toString();
if (name.isEmpty || route.isEmpty) {
print("⚠️ Menu avec valeurs vides: name='$name', route='$route'");
// print("⚠️ Menu avec valeurs vides: name='$name', route='$route'");
return const SizedBox.shrink();
}
@ -391,11 +403,12 @@ class CustomDrawer extends StatelessWidget {
final routeData = routeMapping[route];
if (routeData == null) {
print("⚠️ Route non reconnue: '$route' pour le menu '$name'");
// print("⚠️ Route non reconnue: '$route' pour le menu '$name'");
return ListTile(
leading: const Icon(Icons.help_outline, color: Colors.grey),
title: Text(name),
subtitle: Text("Route: $route", style: const TextStyle(fontSize: 10, color: Colors.grey)),
subtitle: Text("Route: $route",
style: const TextStyle(fontSize: 10, color: Colors.grey)),
onTap: () {
Get.snackbar(
"Route non configurée",
@ -417,7 +430,8 @@ class CustomDrawer extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
// NOUVEAU: Badge Super Admin pour les menus réservés
if ((route == '/demande-assignation' || route == '/approbation-sorties') &&
if ((route == '/demande-assignation' ||
route == '/approbation-sorties') &&
userController.role == 'Super Admin') ...[
Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
@ -437,7 +451,8 @@ class CustomDrawer extends StatelessWidget {
const SizedBox(width: 4),
],
// NOUVEAU: Badge "Tous" pour les menus accessibles à tous
if (route == '/demande-sortie-personnelle' || route == '/historique-sorties-personnelles') ...[
if (route == '/demande-sortie-personnelle' ||
route == '/historique-sorties-personnelles') ...[
Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(
@ -544,7 +559,9 @@ class CustomDrawer extends StatelessWidget {
Row(
children: [
Text(
controller.role.isNotEmpty ? controller.role : 'Aucun rôle',
controller.role.isNotEmpty
? controller.role
: 'Aucun rôle',
style: const TextStyle(
color: Colors.white70,
fontSize: 12,
@ -554,7 +571,8 @@ class CustomDrawer extends StatelessWidget {
if (controller.role == 'Super Admin') ...[
const SizedBox(width: 8),
Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
padding: const EdgeInsets.symmetric(
horizontal: 6, vertical: 2),
decoration: BoxDecoration(
color: Colors.red.shade600,
borderRadius: BorderRadius.circular(8),
@ -586,8 +604,12 @@ class CustomDrawer extends StatelessWidget {
Row(
children: [
Icon(
controller.isCacheReady ? Icons.check_circle : Icons.hourglass_empty,
color: controller.isCacheReady ? Colors.green : Colors.orange,
controller.isCacheReady
? Icons.check_circle
: Icons.hourglass_empty,
color: controller.isCacheReady
? Colors.green
: Colors.orange,
size: 12,
),
const SizedBox(width: 4),
@ -604,7 +626,8 @@ class CustomDrawer extends StatelessWidget {
),
),
// Bouton de rafraîchissement pour les admins
if (controller.role == 'Super Admin' || controller.role == 'Admin') ...[
if (controller.role == 'Super Admin' ||
controller.role == 'Admin') ...[
IconButton(
icon: const Icon(Icons.refresh, color: Colors.white70, size: 20),
onPressed: () async {
@ -630,14 +653,16 @@ class CustomDrawer extends StatelessWidget {
// 🔧 Bouton de debug (à supprimer en production)
if (controller.role == 'Super Admin') ...[
IconButton(
icon: const Icon(Icons.bug_report, color: Colors.white70, size: 18),
icon:
const Icon(Icons.bug_report, color: Colors.white70, size: 18),
onPressed: () {
// Debug des menus
final menus = controller.getUserMenus();
String debugInfo = "MENUS DEBUG:\n";
for (var i = 0; i < menus.length; i++) {
final menu = menus[i];
debugInfo += "[$i] ID:${menu['id']}, Name:'${menu['name']}', Route:'${menu['route']}'\n";
debugInfo +=
"[$i] ID:${menu['id']}, Name:'${menu['name']}', Route:'${menu['route']}'\n";
}
// NOUVEAU: Ajouter info sur les menus sorties personnelles
@ -645,13 +670,15 @@ class CustomDrawer extends StatelessWidget {
debugInfo += "Rôle actuel: ${controller.role}\n";
debugInfo += "Menu Demande Sortie: Accessible à tous\n";
debugInfo += "Menu Historique: Accessible à tous\n";
debugInfo += "Menu Approbation: ${controller.role == 'Super Admin' ? 'Accessible (Super Admin)' : 'Non accessible'}\n";
debugInfo +=
"Menu Approbation: ${controller.role == 'Super Admin' ? 'Accessible (Super Admin)' : 'Non accessible'}\n";
Get.dialog(
AlertDialog(
title: const Text("Debug Menus"),
content: SingleChildScrollView(
child: Text(debugInfo, style: const TextStyle(fontSize: 12)),
child:
Text(debugInfo, style: const TextStyle(fontSize: 12)),
),
actions: [
TextButton(

52
lib/Views/demande_sortie_personnelle_page.dart

@ -56,47 +56,44 @@ class _DemandeSortiePersonnellePageState
}
void _scanQrOrBarcode() async {
// Open the mobile scanner as a modal widget
await showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Container(
width: double.maxFinite,
height: 400, // Adjust according to your needs
height: 400,
child: MobileScanner(
onDetect: (barcodeCapture) {
String scanResult = barcodeCapture.rawValue ?? '';
Navigator.of(context).pop(); // Close dialog after scanning
onDetect: (BarcodeCapture barcodeCap) {
print("BarcodeCapture: $barcodeCap");
// Now accessing the barcodes attribute
final List<Barcode> barcodes = barcodeCap.barcodes;
if (scanResult.isEmpty) return;
if (barcodes.isNotEmpty) {
// Get the first detected barcode value
String? scanResult = barcodes.first.rawValue;
print("Scanned Result: $scanResult");
if (scanResult != null && scanResult.isNotEmpty) {
setState(() {
_searchController.text = scanResult; // Show scanned text
_searchController.text = scanResult;
print(
"Updated Search Controller: ${_searchController.text}");
});
// Assume IMEI is always 15 digits, adjust if necessary
Product? found;
if (scanResult.length == 15 &&
int.tryParse(scanResult) != null) {
found =
_products.firstWhereOrNull((p) => p.imei == scanResult);
// Close dialog after scanning
Navigator.of(context).pop();
// Refresh product list based on new search input
_filterProducts();
} else {
found = _products
.firstWhereOrNull((p) => p.reference == scanResult);
print("Scan result was empty or null.");
Navigator.of(context).pop();
}
if (found != null) {
setState(() {
_selectedProduct = found;
_filteredProducts = [found!];
});
} else {
_showErrorSnackbar('Aucun produit trouvé avec ce code.');
setState(() {
_filteredProducts = [];
_selectedProduct = null;
});
print("No barcodes detected.");
Navigator.of(context).pop();
}
},
),
@ -403,6 +400,9 @@ class _DemandeSortiePersonnellePageState
hintText: 'Rechercher un produit...',
prefixIcon: Icon(Icons.search, color: Colors.grey.shade600),
),
onChanged: (value) {
_filterProducts(); // Call to filter products
},
),
),
IconButton(

2
lib/config/DatabaseConfig.dart

@ -80,7 +80,7 @@ class DatabaseConfig {
config['database']?.toString().isNotEmpty == true &&
config['user'] != null;
} catch (e) {
print("Erreur de validation de la configuration: $e");
// print("Erreur de validation de la configuration: $e");
return false;
}
}

27
lib/controller/HistoryController.dart

@ -27,8 +27,6 @@ class HistoryController extends GetxController {
getTotalSumOrdersByMonth(DateTime.now());
getOrdersByMonth(DateTime.now());
getOrderCountByMonth(DateTime.now());
}
Future<void> fetchOrders() async {
@ -60,9 +58,6 @@ class HistoryController extends GetxController {
}
}
List<DateTime?> getDistinctDates() {
final currentDate = DateTime.now();
final dates = [...orders.map((order) => order.startDate), currentDate]
@ -73,7 +68,9 @@ class HistoryController extends GetxController {
List<Order> filterOrdersByDateRange(DateTime startDate) {
final filteredList = orders
.where((order) => order.startDate != null && order.startDate!.isAtSameMomentAs(startDate))
.where((order) =>
order.startDate != null &&
order.startDate!.isAtSameMomentAs(startDate))
.toList();
filteredOrders.value = filteredList;
return filteredList;
@ -81,7 +78,8 @@ class HistoryController extends GetxController {
Future<List<Order>> getOrdersByStartDate(DateTime startDate) async {
try {
final ordersByStartDate = await _orderDatabase.getOrdersByStartDate(startDate);
final ordersByStartDate =
await _orderDatabase.getOrdersByStartDate(startDate);
return ordersByStartDate;
} catch (e) {
print(e);
@ -91,17 +89,18 @@ class HistoryController extends GetxController {
double getTotalSumOrdersByStartDate(DateTime startDate) {
final filteredOrders = filterOrdersByDateRange(startDate);
double totalSum = filteredOrders.fold(0, (sum, order) => sum + order.totalPrice);
double totalSum =
filteredOrders.fold(0, (sum, order) => sum + order.totalPrice);
return totalSum;
}
Future<RxDouble> getTotalSumOrdersByMonth(DateTime date) async {
final filteredOrders = await getOrdersByMonth(date);
double totalsum = filteredOrders.fold(0, (sum, order) => sum + order.totalPrice);
double totalsum =
filteredOrders.fold(0, (sum, order) => sum + order.totalPrice);
totalSum.value = totalsum;
print(totalSum.value);
// print(totalSum.value);
return totalSum;
}
Future<Map<String, int>> getProductQuantitiesByDate(DateTime date) async {
@ -153,16 +152,10 @@ class HistoryController extends GetxController {
}
}
Future<int> getOrderCountByMonth(DateTime month) async {
List<Order> orders = await getOrdersByMonth(month);
int orderCount = orders.length;
orderQuantity.value = orderCount;
return orderCount;
}
}

14
lib/controller/userController.dart

@ -69,7 +69,7 @@ class UserController extends GetxController {
// Précharger les permissions en arrière-plan (non bloquant)
_preloadPermissionsInBackground();
} catch (dbError) {
print("❌ Erreur BDD, utilisation du fallback: $dbError");
// print("❌ Erreur BDD, utilisation du fallback: $dbError");
_username.value = storedUsername;
_email.value = prefs.getString('email') ?? '';
_role.value = storedRole;
@ -84,7 +84,7 @@ class UserController extends GetxController {
}
}
} catch (e) {
print('❌ Erreur lors du chargement des données utilisateur: $e');
// print('❌ Erreur lors du chargement des données utilisateur: $e');
}
}
@ -129,10 +129,10 @@ class UserController extends GetxController {
_userId.value = userId;
_pointDeVenteId.value = user.pointDeVenteId ?? 0;
print("✅ Utilisateur mis à jour avec credentials:");
print(" Username: ${_username.value}");
print(" Role: ${_role.value}");
print(" UserID: ${_userId.value}");
// print("✅ Utilisateur mis à jour avec credentials:");
// print(" Username: ${_username.value}");
// print(" Role: ${_role.value}");
// print(" UserID: ${_userId.value}");
saveUserData();
@ -166,7 +166,7 @@ class UserController extends GetxController {
await prefs.setString(
'point_de_vente_designation', _pointDeVenteDesignation.value);
print("✅ Données sauvegardées avec succès");
// print("✅ Données sauvegardées avec succès");
} catch (e) {
print('❌ Erreur lors de la sauvegarde: $e');
}

24
lib/main.dart

@ -9,34 +9,34 @@ void main() async {
WidgetsFlutterBinding.ensureInitialized();
try {
print("Initialisation de l'application...");
// print("Initialisation de l'application...");
// Pour le développement : supprimer toutes les tables (équivalent à deleteDatabaseFile)
// ATTENTION: Décommentez seulement si vous voulez réinitialiser la base
// await AppDatabase.instance.deleteDatabaseFile();
// // Pour le développement : supprimer toutes les tables (équivalent à deleteDatabaseFile)
// // ATTENTION: Décommentez seulement si vous voulez réinitialiser la base
// // await AppDatabase.instance.deleteDatabaseFile();
// Initialiser la base de données MySQL
print("Connexion à la base de données MySQL...");
// await AppDatabase.instance.initDatabase();
print("Base de données initialisée avec succès !");
// // Initialiser la base de données MySQL
// print("Connexion à la base de données MySQL...");
// // await AppDatabase.instance.initDatabase();
// print("Base de données initialisée avec succès !");
// Afficher les informations de la base (pour debug)
await AppDatabase.instance.printDatabaseInfo();
// Initialiser le contrôleur utilisateur
Get.put(UserController());
print("Contrôleur utilisateur initialisé");
// print("Contrôleur utilisateur initialisé");
// Configurer le logger
setupLogger();
print("Lancement de l'application...");
// print("Lancement de l'application...");
runApp(const GetMaterialApp(
debugShowCheckedModeBanner: false,
home: MyApp(),
));
} catch (e) {
print('Erreur lors de l\'initialisation: $e');
// print('Erreur lors de l\'initialisation: $e');
// Afficher une page d'erreur avec plus de détails
runApp(MaterialApp(
@ -129,6 +129,6 @@ void main() async {
void setupLogger() {
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((record) {
print('${record.level.name}: ${record.time}: ${record.message}');
// print('${record.level.name}: ${record.time}: ${record.message}');
});
}
Loading…
Cancel
Save