import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:get/get_core/src/get_main.dart'; import 'package:youmazgestion/Models/produit.dart'; //import 'package:youmazgestion/Services/productDatabase.dart'; import 'package:youmazgestion/Components/app_bar.dart'; import 'package:youmazgestion/Components/appDrawer.dart'; import 'package:youmazgestion/Services/stock_managementDatabase.dart'; class GestionStockPage extends StatefulWidget { const GestionStockPage({super.key}); @override _GestionStockPageState createState() => _GestionStockPageState(); } class _GestionStockPageState extends State { final AppDatabase _database = AppDatabase.instance; List _products = []; List _filteredProducts = []; String? _selectedCategory; int? _selectedIdPointDeVente; // Nouveau filtre final TextEditingController _searchController = TextEditingController(); bool _showLowStockOnly = false; bool _sortByStockAscending = false; @override void initState() { super.initState(); _loadProducts(); _searchController.addListener(_filterProducts); } Future _loadProducts() async { final products = await _database.getProducts(); setState(() { _products = products; _filterProducts(); }); } void _filterProducts() { final query = _searchController.text.toLowerCase(); setState(() { _filteredProducts = _products.where((product) { final matchesSearch = product.name.toLowerCase().contains(query) || (product.reference?.toLowerCase().contains(query) ?? false); final matchesCategory = _selectedCategory == null || product.category == _selectedCategory; final matchesPointDeVente = _selectedIdPointDeVente == null || product.pointDeVenteId == _selectedIdPointDeVente; // Nouveau filtre final matchesStockFilter = !_showLowStockOnly || (product.stock ?? 0) <= 5; // Seuil pour stock faible return matchesSearch && matchesCategory && matchesPointDeVente && matchesStockFilter; }).toList(); // Trier les produits _filteredProducts.sort((a, b) { if (_sortByStockAscending) { return (a.stock ?? 0).compareTo(b.stock ?? 0); } else { return (b.stock ?? 0).compareTo(a.stock ?? 0); } }); }); } Future _updateStock(Product product, int newStock) async { await _database.updateStock(product.id!, newStock); await _loadProducts(); Get.snackbar( 'Succès', 'Stock mis à jour pour ${product.name}', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.green, colorText: Colors.white, duration: const Duration(seconds: 2), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar(title: 'Gestion des Stocks'), drawer: CustomDrawer(), body: Column( children: [ // Filtres et recherche Container( padding: const EdgeInsets.all(16.0), decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 4, offset: const Offset(0, 2), ), ], ), child: Column( children: [ // Barre de recherche TextField( controller: _searchController, decoration: InputDecoration( labelText: 'Rechercher un produit', prefixIcon: const Icon(Icons.search), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), ), ), const SizedBox(height: 12), // Filtres - Première ligne Row( children: [ // Filtre par catégorie Expanded( child: FutureBuilder>( future: _database.getCategories(), builder: (context, snapshot) { if (!snapshot.hasData) { return const SizedBox(); } final categories = snapshot.data!; return DropdownButtonFormField( value: _selectedCategory, decoration: InputDecoration( labelText: 'Catégorie', border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), ), items: [ const DropdownMenuItem( value: null, child: Text('Toutes les catégories'), ), ...categories.map((category) { return DropdownMenuItem( value: category, child: Text(category), ); }), ], onChanged: (value) { setState(() { _selectedCategory = value; _filterProducts(); }); }, ); }, ), ), const SizedBox(width: 12), // Filtre par point de vente Expanded( child: FutureBuilder>>( future: _database.getPointsDeVente(), // Vous devez implémenter cette méthode builder: (context, snapshot) { if (!snapshot.hasData) { return const SizedBox(); } final pointsDeVente = snapshot.data!; return DropdownButtonFormField( value: _selectedIdPointDeVente, decoration: InputDecoration( labelText: 'Point de vente', border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), ), items: [ const DropdownMenuItem( value: null, child: Text('Tous les points de vente'), ), ...pointsDeVente.map((point) { return DropdownMenuItem( value: point['id'], child: Text(point['nom'] ?? 'Point ${point['id']}'), ); }), ], onChanged: (value) { setState(() { _selectedIdPointDeVente = value; _filterProducts(); }); }, ); }, ), ), ], ), const SizedBox(height: 12), // Filtres - Deuxième ligne Row( children: [ // Toggle pour stock faible seulement Container( decoration: BoxDecoration( border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(12), ), padding: const EdgeInsets.symmetric(horizontal: 12), child: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.warning_amber, size: 20), const SizedBox(width: 8), const Text('Stock faible'), Switch( value: _showLowStockOnly, onChanged: (value) { setState(() { _showLowStockOnly = value; _filterProducts(); }); }, activeColor: Colors.orange, ), ], ), ), ], ), // Tri const SizedBox(height: 12), Row( children: [ const Text('Trier par stock:'), const SizedBox(width: 8), ChoiceChip( label: const Text('Croissant'), selected: _sortByStockAscending, onSelected: (selected) { setState(() { _sortByStockAscending = true; _filterProducts(); }); }, ), const SizedBox(width: 8), ChoiceChip( label: const Text('Décroissant'), selected: !_sortByStockAscending, onSelected: (selected) { setState(() { _sortByStockAscending = false; _filterProducts(); }); }, ), ], ), ], ), ), // Statistiques rapides Container( padding: const EdgeInsets.symmetric(vertical: 8), color: Colors.grey.shade100, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildStatCard( 'Total', '${_products.length}', Icons.inventory, Colors.blue, ), _buildStatCard( 'En stock', '${_products.where((p) => (p.stock ?? 0) > 0).length}', Icons.check_circle, Colors.green, ), _buildStatCard( 'Stock faible', '${_products.where((p) => (p.stock ?? 0) <= 5).length}', Icons.warning, Colors.orange, ), _buildStatCard( 'Rupture', '${_products.where((p) => (p.stock ?? 0) == 0).length}', Icons.cancel, Colors.red, ), ], ), ), // Liste des produits Expanded( child: _filteredProducts.isEmpty ? const Center( child: Text('Aucun produit trouvé'), ) : ListView.builder( padding: const EdgeInsets.all(8), itemCount: _filteredProducts.length, itemBuilder: (context, index) { final product = _filteredProducts[index]; return _buildProductCard(product); }, ), ), ], ), floatingActionButton: FloatingActionButton( onPressed: () => _showAddStockDialog(null), child: const Icon(Icons.add), ), ); } Widget _buildStatCard(String title, String value, IconData icon, Color color) { return Column( children: [ Icon(icon, color: color), const SizedBox(height: 4), Text( value, style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: color, ), ), Text( title, style: const TextStyle(fontSize: 12), ), ], ); } Widget _buildProductCard(Product product) { final stock = product.stock ?? 0; Color stockColor; IconData stockIcon; if (stock == 0) { stockColor = Colors.red; stockIcon = Icons.block; } else if (stock <= 5) { stockColor = Colors.orange; stockIcon = Icons.warning; } else { stockColor = Colors.green; stockIcon = Icons.check_circle; } return Card( margin: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), child: ListTile( leading: product.image != null && product.image!.isNotEmpty ? CircleAvatar( backgroundImage: NetworkImage(product.image!), ) : CircleAvatar( backgroundColor: Colors.blue.shade100, child: Text(product.name[0]), ), title: Text(product.name), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Catégorie: ${product.category}'), if (product.pointDeVentelib != null) Text('Point de vente: ${product.pointDeVentelib}'), ], ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Row( children: [ Icon(stockIcon, size: 16, color: stockColor), const SizedBox(width: 4), Text( '$stock', style: TextStyle( fontWeight: FontWeight.bold, color: stockColor, ), ), ], ), const SizedBox(height: 4), Text( '${product.price.toStringAsFixed(2)} DA', style: const TextStyle(fontSize: 12), ), ], ), IconButton( icon: const Icon(Icons.edit), onPressed: () => _showAddStockDialog(product), ), ], ), ), ); } void _showAddStockDialog(Product? product) { final isNew = product == null; final controller = TextEditingController( text: isNew ? '' : product.stock?.toString() ?? '0', ); showDialog( context: context, builder: (context) { return AlertDialog( title: Text(isNew ? 'Ajouter un produit' : 'Modifier le stock'), content: Column( mainAxisSize: MainAxisSize.min, children: [ if (isNew) TextField( decoration: const InputDecoration(labelText: 'Nom du produit'), ), if (isNew) const SizedBox(height: 12), TextField( controller: controller, decoration: const InputDecoration(labelText: 'Quantité en stock'), keyboardType: TextInputType.number, ), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Annuler'), ), ElevatedButton( onPressed: () async { final newStock = int.tryParse(controller.text) ?? 0; if (isNew) { // TODO: Implémenter l'ajout d'un nouveau produit } else { await _updateStock(product, newStock); } Navigator.pop(context); }, child: Text(isNew ? 'Ajouter' : 'Mettre à jour'), ), ], ); }, ); } @override void dispose() { _searchController.dispose(); super.dispose(); } }