import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:youmazgestion/Models/client.dart'; import 'package:youmazgestion/Models/produit.dart'; import 'package:youmazgestion/Services/stock_managementDatabase.dart'; class HistoriquePage extends StatefulWidget { const HistoriquePage({super.key}); @override _HistoriquePageState createState() => _HistoriquePageState(); } class _HistoriquePageState extends State { final AppDatabase _appDatabase = AppDatabase.instance; List _commandes = []; bool _isLoading = true; DateTimeRange? _dateRange; final TextEditingController _searchController = TextEditingController(); @override void initState() { super.initState(); _loadCommandes(); } Future _loadCommandes() async { setState(() { _isLoading = true; }); try { final commandes = await _appDatabase.getCommandes(); setState(() { _commandes = commandes; _isLoading = false; }); } catch (e) { setState(() { _isLoading = false; }); Get.snackbar( 'Erreur', 'Impossible de charger les commandes: ${e.toString()}', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red, colorText: Colors.white, ); } } Future _selectDateRange(BuildContext context) async { final DateTimeRange? picked = await showDateRangePicker( context: context, firstDate: DateTime(2020), lastDate: DateTime.now().add(const Duration(days: 365)), initialDateRange: _dateRange ?? DateTimeRange( start: DateTime.now().subtract(const Duration(days: 30)), end: DateTime.now(), ), ); if (picked != null) { setState(() { _dateRange = picked; }); _filterCommandes(); } } void _filterCommandes() { final searchText = _searchController.text.toLowerCase(); setState(() { _isLoading = true; }); _appDatabase.getCommandes().then((commandes) { List filtered = commandes; // Filtre par date if (_dateRange != null) { filtered = filtered.where((commande) { final date = commande.dateCommande; return date.isAfter(_dateRange!.start) && date.isBefore(_dateRange!.end.add(const Duration(days: 1))); }).toList(); } // Filtre par recherche if (searchText.isNotEmpty) { filtered = filtered.where((commande) { return commande.clientNom!.toLowerCase().contains(searchText) || commande.clientPrenom!.toLowerCase().contains(searchText) || commande.id.toString().contains(searchText); }).toList(); } setState(() { _commandes = filtered; _isLoading = false; }); }); } void _showCommandeDetails(Commande commande) async { final details = await _appDatabase.getDetailsCommande(commande.id!); final client = await _appDatabase.getClientById(commande.clientId); Get.bottomSheet( Container( padding: const EdgeInsets.all(16), height: MediaQuery.of(context).size.height * 0.7, decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Commande #${commande.id}', style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), IconButton( icon: const Icon(Icons.close), onPressed: () => Get.back(), ), ], ), const Divider(), Text( 'Client: ${client?.nom} ${client?.prenom}', style: const TextStyle(fontSize: 16), ), Text( 'Date: ${commande.dateCommande}', style: const TextStyle(fontSize: 16), ), Text( 'Statut: ${_getStatutText(commande.statut)}', style: TextStyle( fontSize: 16, color: _getStatutColor(commande.statut), fontWeight: FontWeight.bold, ), ), const SizedBox(height: 16), const Text( 'Articles:', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), Expanded( child: ListView.builder( itemCount: details.length, itemBuilder: (context, index) { final detail = details[index]; return ListTile( leading: const Icon(Icons.shopping_bag), title: Text(detail.produitNom ?? 'Produit inconnu'), subtitle: Text( '${detail.quantite} x ${detail.prixUnitaire.toStringAsFixed(2)} DA', ), trailing: Text( '${detail.sousTotal.toStringAsFixed(2)} DA', style: const TextStyle(fontWeight: FontWeight.bold), ), ); }, ), ), const Divider(), Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Total:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), Text( '${commande.montantTotal.toStringAsFixed(2)} DA', style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.green, ), ), ], ), ), if (commande.statut == StatutCommande.enAttente || commande.statut == StatutCommande.enPreparation) ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.blue.shade800, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), ), onPressed: () => _updateStatutCommande(commande.id!), child: const Text('Marquer comme livrée'), ), ], ), ), ); } String _getStatutText(StatutCommande statut) { switch (statut) { case StatutCommande.enAttente: return 'En attente'; case StatutCommande.confirmee: return 'Confirmée'; case StatutCommande.enPreparation: return 'En préparation'; case StatutCommande.livree: return 'Livrée'; case StatutCommande.annulee: return 'Annulée'; default: return 'Inconnu'; } } Color _getStatutColor(StatutCommande statut) { switch (statut) { case StatutCommande.enAttente: return Colors.orange; case StatutCommande.confirmee: return Colors.blue; case StatutCommande.enPreparation: return Colors.purple; case StatutCommande.livree: return Colors.green; case StatutCommande.annulee: return Colors.red; default: return Colors.grey; } } Future _updateStatutCommande(int commandeId) async { try { await _appDatabase.updateStatutCommande( commandeId, StatutCommande.livree); Get.back(); // Ferme le bottom sheet _loadCommandes(); Get.snackbar( 'Succès', 'Statut de la commande mis à jour', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.green, colorText: Colors.white, ); } catch (e) { Get.snackbar( 'Erreur', 'Impossible de mettre à jour le statut: ${e.toString()}', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red, colorText: Colors.white, ); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Historique des Commandes'), actions: [ IconButton( icon: const Icon(Icons.refresh), onPressed: _loadCommandes, ), ], ), body: Column( children: [ Padding( padding: const EdgeInsets.all(8), child: Row( children: [ Expanded( child: TextField( controller: _searchController, decoration: InputDecoration( labelText: 'Rechercher', prefixIcon: const Icon(Icons.search), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), ), suffixIcon: IconButton( icon: const Icon(Icons.clear), onPressed: () { _searchController.clear(); _filterCommandes(); }, ), ), onChanged: (value) => _filterCommandes(), ), ), IconButton( icon: const Icon(Icons.date_range), onPressed: () => _selectDateRange(context), ), ], ), ), if (_dateRange != null) Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( DateFormat('dd/MM/yyyy').format(_dateRange!.start), style: const TextStyle(fontWeight: FontWeight.bold), ), const Text(' - '), Text( DateFormat('dd/MM/yyyy').format(_dateRange!.end), style: const TextStyle(fontWeight: FontWeight.bold), ), IconButton( icon: const Icon(Icons.close, size: 18), onPressed: () { setState(() { _dateRange = null; }); _filterCommandes(); }, ), ], ), ), Expanded( child: _isLoading ? const Center(child: CircularProgressIndicator()) : _commandes.isEmpty ? const Center( child: Text('Aucune commande trouvée'), ) : ListView.builder( itemCount: _commandes.length, itemBuilder: (context, index) { final commande = _commandes[index]; return Card( margin: const EdgeInsets.symmetric( horizontal: 8, vertical: 4), child: ListTile( leading: const Icon(Icons.shopping_cart), title: Text( 'Commande #${commande.id} - ${commande.clientNom} ${commande.clientPrenom}'), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( commande.dateCommande as String ), Text( '${commande.montantTotal.toStringAsFixed(2)} DA', style: const TextStyle( fontWeight: FontWeight.bold), ), ], ), trailing: Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4), decoration: BoxDecoration( color: _getStatutColor(commande.statut) .withOpacity(0.2), borderRadius: BorderRadius.circular(12), ), child: Text( _getStatutText(commande.statut), style: TextStyle( color: _getStatutColor(commande.statut), fontWeight: FontWeight.bold, ), ), ), onTap: () => _showCommandeDetails(commande), ), ); }, ), ), ], ), ); } }