import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:pdf/pdf.dart'; import 'package:pdf/widgets.dart' as pw; import 'package:path_provider/path_provider.dart'; import 'package:open_file/open_file.dart'; import 'package:youmazgestion/Components/app_bar.dart'; import 'package:youmazgestion/Components/appDrawer.dart'; import 'package:youmazgestion/Models/client.dart'; import 'package:youmazgestion/Services/productDatabase.dart'; class GestionCommandesPage extends StatefulWidget { const GestionCommandesPage({super.key}); @override _GestionCommandesPageState createState() => _GestionCommandesPageState(); } class _GestionCommandesPageState extends State { final ProductDatabase _database = ProductDatabase.instance; List _commandes = []; List _filteredCommandes = []; StatutCommande? _selectedStatut; DateTime? _selectedDate; final TextEditingController _searchController = TextEditingController(); bool _showCancelledOrders = false; // Nouveau: contrôle l'affichage des commandes annulées @override void initState() { super.initState(); _loadCommandes(); _searchController.addListener(_filterCommandes); } Future _loadCommandes() async { final commandes = await _database.getCommandes(); setState(() { _commandes = commandes; _filterCommandes(); }); } Future loadImage() async { final data = await rootBundle.load('assets/youmaz2.png'); return data.buffer.asUint8List(); } void _filterCommandes() { final query = _searchController.text.toLowerCase(); setState(() { _filteredCommandes = _commandes.where((commande) { final matchesSearch = commande.clientNomComplet.toLowerCase().contains(query) || commande.id.toString().contains(query); final matchesStatut = _selectedStatut == null || commande.statut == _selectedStatut; final matchesDate = _selectedDate == null || DateFormat('yyyy-MM-dd').format(commande.dateCommande) == DateFormat('yyyy-MM-dd').format(_selectedDate!); // Nouveau: filtrer les commandes annulées selon le toggle final shouldShowCancelled = _showCancelledOrders || commande.statut != StatutCommande.annulee; return matchesSearch && matchesStatut && matchesDate && shouldShowCancelled; }).toList(); }); } Future _updateStatut(int commandeId, StatutCommande newStatut) async { await _database.updateStatutCommande(commandeId, newStatut); await _loadCommandes(); // Amélioration: message plus spécifique selon le statut String message = 'Statut de la commande mis à jour'; Color backgroundColor = Colors.green; switch (newStatut) { case StatutCommande.annulee: message = 'Commande annulée avec succès'; backgroundColor = Colors.orange; break; case StatutCommande.livree: message = 'Commande marquée comme livrée'; backgroundColor = Colors.green; break; case StatutCommande.confirmee: message = 'Commande confirmée'; backgroundColor = Colors.blue; break; default: break; } Get.snackbar( 'Succès', message, snackPosition: SnackPosition.BOTTOM, backgroundColor: backgroundColor, colorText: Colors.white, duration: const Duration(seconds: 2), ); } Future _generateInvoice(Commande commande) async { final details = await _database.getDetailsCommande(commande.id!); final client = await _database.getClientById(commande.clientId); final pdf = pw.Document(); final imageBytes = await loadImage(); // Charge les données de l'image final image = pw.MemoryImage(imageBytes); // Amélioration: styles plus professionnels final headerStyle = pw.TextStyle( fontSize: 18, fontWeight: pw.FontWeight.bold, color: PdfColors.blue900, ); final titleStyle = pw.TextStyle( fontSize: 14, fontWeight: pw.FontWeight.bold, ); final subtitleStyle = pw.TextStyle( fontSize: 12, color: PdfColors.grey600, ); // Contenu du PDF amélioré pdf.addPage( pw.Page( margin: const pw.EdgeInsets.all(20), build: (pw.Context context) { return pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ // En-tête avec logo (si disponible) pw.Row( mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ // Placeholder pour le logo - à remplacer par votre logo pw.Container( width: 100, height: 80, decoration: pw.BoxDecoration( border: pw.Border.all(color: PdfColors.blue900, width: 2), borderRadius: pw.BorderRadius.circular(8), ), child: pw.Center( child: pw.Image(image) ), ), pw.SizedBox(height: 10), pw.Text('guycom', style: headerStyle), pw.Text('123 Rue des Entreprises', style: subtitleStyle), pw.Text('Antananarivo, Madagascar', style: subtitleStyle), pw.Text('Tél: +213 123 456 789', style: subtitleStyle), pw.Text('Site: guycom.mg', style: subtitleStyle), ], ), pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.end, children: [ pw.Container( padding: const pw.EdgeInsets.all(12), decoration: pw.BoxDecoration( color: PdfColors.blue50, borderRadius: pw.BorderRadius.circular(8), ), child: pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ pw.Text('FACTURE', style: pw.TextStyle( fontSize: 20, fontWeight: pw.FontWeight.bold, color: PdfColors.blue900, ), ), pw.SizedBox(height: 8), pw.Text('N°: ${commande.id}', style: titleStyle), pw.Text('Date: ${DateFormat('dd/MM/yyyy').format(commande.dateCommande)}'), ], ), ), ], ), ], ), pw.SizedBox(height: 30), // Informations client pw.Container( width: double.infinity, padding: const pw.EdgeInsets.all(12), decoration: pw.BoxDecoration( color: PdfColors.grey100, borderRadius: pw.BorderRadius.circular(8), ), child: pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ pw.Text('FACTURÉ À:', style: titleStyle), pw.SizedBox(height: 5), pw.Text(client?.nomComplet ?? 'Client inconnu', style: pw.TextStyle(fontSize: 12)), if (client?.telephone != null) pw.Text('Tél: ${client!.telephone}', style: pw.TextStyle(fontSize: 10, color: PdfColors.grey600)), ], ), ), pw.SizedBox(height: 30), // Tableau des produits pw.Text('DÉTAILS DE LA COMMANDE', style: titleStyle), pw.SizedBox(height: 10), pw.Table( border: pw.TableBorder.all(color: PdfColors.grey400, width: 0.5), children: [ pw.TableRow( decoration: const pw.BoxDecoration(color: PdfColors.blue900), children: [ _buildTableCell('Produit', titleStyle.copyWith(color: PdfColors.white)), _buildTableCell('Qté', titleStyle.copyWith(color: PdfColors.white)), _buildTableCell('Prix unit.', titleStyle.copyWith(color: PdfColors.white)), _buildTableCell('Total', titleStyle.copyWith(color: PdfColors.white)), ], ), ...details.asMap().entries.map((entry) { final index = entry.key; final detail = entry.value; final isEven = index % 2 == 0; return pw.TableRow( decoration: pw.BoxDecoration( color: isEven ? PdfColors.white : PdfColors.grey50, ), children: [ _buildTableCell(detail.produitNom ?? 'Produit inconnu'), _buildTableCell(detail.quantite.toString()), _buildTableCell('${detail.prixUnitaire.toStringAsFixed(2)} DA'), _buildTableCell('${detail.sousTotal.toStringAsFixed(2)} DA'), ], ); }), ], ), pw.SizedBox(height: 20), // Total pw.Container( alignment: pw.Alignment.centerRight, child: pw.Container( padding: const pw.EdgeInsets.all(12), decoration: pw.BoxDecoration( color: PdfColors.blue900, borderRadius: pw.BorderRadius.circular(8), ), child: pw.Text( 'TOTAL: ${commande.montantTotal.toStringAsFixed(2)} DA', style: pw.TextStyle( fontSize: 16, fontWeight: pw.FontWeight.bold, color: PdfColors.white, ), ), ), ), pw.Spacer(), // Pied de page pw.Container( width: double.infinity, padding: const pw.EdgeInsets.all(12), decoration: pw.BoxDecoration( border: pw.Border( top: pw.BorderSide(color: PdfColors.grey400, width: 1), ), ), child: pw.Column( children: [ pw.Text( 'Merci pour votre confiance!', style: pw.TextStyle( fontSize: 14, fontStyle: pw.FontStyle.italic, color: PdfColors.blue900, ), ), pw.SizedBox(height: 5), pw.Text( 'Cette facture est générée automatiquement par le système Youmaz Gestion', style: pw.TextStyle(fontSize: 8, color: PdfColors.grey600), ), ], ), ), ], ); }, ), ); // Sauvegarder le PDF final output = await getTemporaryDirectory(); final file = File('${output.path}/facture_${commande.id}.pdf'); await file.writeAsBytes(await pdf.save()); // Ouvrir le PDF await OpenFile.open(file.path); } pw.Widget _buildTableCell(String text, [pw.TextStyle? style]) { return pw.Padding( padding: const pw.EdgeInsets.all(8.0), child: pw.Text(text, style: style ?? pw.TextStyle(fontSize: 10)), ); } Color _getStatutColor(StatutCommande statut) { switch (statut) { case StatutCommande.enAttente: return Colors.orange.shade100; case StatutCommande.confirmee: return Colors.blue.shade100; case StatutCommande.enPreparation: return Colors.amber.shade100; case StatutCommande.expediee: return Colors.purple.shade100; case StatutCommande.livree: return Colors.green.shade100; case StatutCommande.annulee: return Colors.red.shade100; } } IconData _getStatutIcon(StatutCommande statut) { switch (statut) { case StatutCommande.enAttente: return Icons.schedule; case StatutCommande.confirmee: return Icons.check_circle_outline; case StatutCommande.enPreparation: return Icons.settings; case StatutCommande.expediee: return Icons.local_shipping; case StatutCommande.livree: return Icons.check_circle; case StatutCommande.annulee: return Icons.cancel; } } @override Widget build(BuildContext context) { return Scaffold( appBar: const CustomAppBar(title: 'Gestion des Commandes'), drawer: CustomDrawer(), body: Column( children: [ // Header avec logo et statistiques Container( padding: const EdgeInsets.all(16.0), decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.blue.shade50, Colors.white], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), child: Column( children: [ // Logo et titre Row( children: [ // Logo de l'entreprise Container( width: 50, height: 50, decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 4, offset: const Offset(0, 2), ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(8), child: Image.asset( 'assets/logo.png', // Remplacez par le chemin de votre logo fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return Container( decoration: BoxDecoration( color: Colors.blue.shade900, borderRadius: BorderRadius.circular(8), ), child: const Icon( Icons.business, color: Colors.white, size: 30, ), ); }, ), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Gestion des Commandes', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.black87, ), ), Text( '${_filteredCommandes.length} commande(s) affichée(s)', style: TextStyle( fontSize: 14, color: Colors.grey.shade600, ), ), ], ), ), ], ), const SizedBox(height: 16), // Barre de recherche améliorée Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 4, offset: const Offset(0, 2), ), ], ), child: TextField( controller: _searchController, decoration: InputDecoration( labelText: 'Rechercher par client ou numéro de commande', prefixIcon: Icon(Icons.search, color: Colors.blue.shade800), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none, ), filled: true, fillColor: Colors.white, contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12, ), ), ), ), const SizedBox(height: 16), // Filtres améliorés Row( children: [ Expanded( child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 4, offset: const Offset(0, 2), ), ], ), child: DropdownButtonFormField( value: _selectedStatut, decoration: InputDecoration( labelText: 'Filtrer par statut', prefixIcon: Icon(Icons.filter_list, color: Colors.blue.shade600), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none, ), filled: true, fillColor: Colors.white, contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12, ), ), items: [ const DropdownMenuItem( value: null, child: Text('Tous les statuts'), ), ...StatutCommande.values.map((statut) { return DropdownMenuItem( value: statut, child: Row( children: [ Icon(_getStatutIcon(statut), size: 16), const SizedBox(width: 8), Text(statutLibelle(statut)), ], ), ); }), ], onChanged: (value) { setState(() { _selectedStatut = value; _filterCommandes(); }); }, ), ), ), const SizedBox(width: 12), Expanded( child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 4, offset: const Offset(0, 2), ), ], ), child: TextButton.icon( style: TextButton.styleFrom( padding: const EdgeInsets.symmetric( vertical: 16, horizontal: 12, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), onPressed: () async { final date = await showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime(2020), lastDate: DateTime.now(), builder: (context, child) { return Theme( data: Theme.of(context).copyWith( colorScheme: ColorScheme.light( primary: Colors.blue.shade900, ), ), child: child!, ); }, ); if (date != null) { setState(() { _selectedDate = date; _filterCommandes(); }); } }, icon: Icon(Icons.calendar_today, color: Colors.blue.shade600), label: Text( _selectedDate == null ? 'Date' : DateFormat('dd/MM/yyyy').format(_selectedDate!), style: const TextStyle(color: Colors.black87), ), ), ), ), const SizedBox(width: 12), // Bouton reset Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 4, offset: const Offset(0, 2), ), ], ), child: IconButton( icon: Icon(Icons.refresh, color: Colors.blue.shade600), onPressed: () { setState(() { _selectedStatut = null; _selectedDate = null; _searchController.clear(); _filterCommandes(); }); }, tooltip: 'Réinitialiser les filtres', ), ), ], ), const SizedBox(height: 12), // Toggle pour afficher/masquer les commandes annulées Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 4, offset: const Offset(0, 2), ), ], ), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Row( children: [ Icon( Icons.visibility, size: 20, color: Colors.grey.shade600, ), const SizedBox(width: 8), Text( 'Afficher commandes annulées', style: TextStyle( fontSize: 14, color: Colors.grey.shade700, ), ), const Spacer(), Switch( value: _showCancelledOrders, onChanged: (value) { setState(() { _showCancelledOrders = value; _filterCommandes(); }); }, activeColor: Colors.blue.shade600, ), ], ), ), ], ), ), // Liste des commandes Expanded( child: _filteredCommandes.isEmpty ? Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.inbox, size: 64, color: Colors.grey.shade400, ), const SizedBox(height: 16), Text( 'Aucune commande trouvée', style: TextStyle( fontSize: 18, color: Colors.grey.shade600, fontWeight: FontWeight.w500, ), ), const SizedBox(height: 8), Text( 'Essayez de modifier vos filtres', style: TextStyle( fontSize: 14, color: Colors.grey.shade500, ), ), ], ), ) : ListView.builder( padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: _filteredCommandes.length, itemBuilder: (context, index) { final commande = _filteredCommandes[index]; return Container( margin: const EdgeInsets.only(bottom: 12), decoration: BoxDecoration( color: _getStatutColor(commande.statut), borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 4, offset: const Offset(0, 2), ), ], ), child: ExpansionTile( tilePadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 8, ), leading: Container( width: 50, height: 50, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(25), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 2, offset: const Offset(0, 1), ), ], ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( _getStatutIcon(commande.statut), size: 20, color: commande.statut == StatutCommande.annulee ? Colors.red : Colors.blue.shade600, ), Text( '#${commande.id}', style: const TextStyle( fontSize: 10, fontWeight: FontWeight.bold, ), ), ], ), ), title: Text( commande.clientNomComplet, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 4), Row( children: [ Icon( Icons.calendar_today, size: 14, color: Colors.grey.shade600, ), const SizedBox(width: 4), Text( DateFormat('dd/MM/yyyy').format(commande.dateCommande), style: TextStyle( fontSize: 12, color: Colors.grey.shade600, ), ), const SizedBox(width: 16), Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 2, ), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), ), child: Text( commande.statutLibelle, style: TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: commande.statut == StatutCommande.annulee ? Colors.red : Colors.blue.shade700, ), ), ), ], ), const SizedBox(height: 4), Row( children: [ Icon( Icons.attach_money, size: 14, color: Colors.green.shade600, ), const SizedBox(width: 4), Text( '${commande.montantTotal.toStringAsFixed(2)} DA', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Colors.green.shade700, ), ), ], ), ], ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 2, offset: const Offset(0, 1), ), ], ), child: IconButton( icon: Icon( Icons.receipt_long, color: Colors.blue.shade600, ), onPressed: () => _generateInvoice(commande), tooltip: 'Générer la facture', ), ), ], ), children: [ Container( padding: const EdgeInsets.all(16.0), decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( bottomLeft: Radius.circular(12), bottomRight: Radius.circular(12), ), ), child: Column( children: [ _CommandeDetails(commande: commande), const SizedBox(height: 16), if (commande.statut != StatutCommande.annulee) _CommandeActions( commande: commande, onStatutChanged: _updateStatut, ), ], ), ), ], ), ); }, ), ), ], ), ); } String statutLibelle(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.expediee: return 'Expédiée'; case StatutCommande.livree: return 'Livrée'; case StatutCommande.annulee: return 'Annulée'; } } @override void dispose() { _searchController.dispose(); super.dispose(); } } class _CommandeDetails extends StatelessWidget { final Commande commande; const _CommandeDetails({required this.commande}); @override Widget build(BuildContext context) { return FutureBuilder>( future: ProductDatabase.instance.getDetailsCommande(commande.id!), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (!snapshot.hasData || snapshot.data!.isEmpty) { return const Text('Aucun détail disponible'); } final details = snapshot.data!; return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.blue.shade50, borderRadius: BorderRadius.circular(8), ), child: const Text( 'Détails de la commande', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, color: Colors.black87, ), ), ), const SizedBox(height: 12), Container( decoration: BoxDecoration( border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(8), ), child: Table( children: [ TableRow( decoration: BoxDecoration( color: Colors.grey.shade100, ), children: [ _buildTableHeader('Produit'), _buildTableHeader('Qté'), _buildTableHeader('Prix unit.'), _buildTableHeader('Total'), ], ), ...details.map((detail) => TableRow( children: [ _buildTableCell(detail.produitNom ?? 'Produit inconnu'), _buildTableCell('${detail.quantite}'), _buildTableCell('${detail.prixUnitaire.toStringAsFixed(2)} DA'), _buildTableCell('${detail.sousTotal.toStringAsFixed(2)} DA'), ], )), ], ), ), const SizedBox(height: 12), Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.green.shade50, borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.green.shade200), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Total de la commande:', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), ), Text( '${commande.montantTotal.toStringAsFixed(2)} DA', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, color: Colors.green.shade700, ), ), ], ), ), ], ); }, ); } Widget _buildTableHeader(String text) { return Padding( padding: const EdgeInsets.all(8.0), child: Text( text, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 14, ), textAlign: TextAlign.center, ), ); } Widget _buildTableCell(String text) { return Padding( padding: const EdgeInsets.all(8.0), child: Text( text, style: const TextStyle(fontSize: 13), textAlign: TextAlign.center, ), ); } } class _CommandeActions extends StatelessWidget { final Commande commande; final Function(int, StatutCommande) onStatutChanged; const _CommandeActions({ required this.commande, required this.onStatutChanged, }); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.grey.shade50, borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.grey.shade200), ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text( 'Actions sur la commande', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), ), const SizedBox(height: 12), Wrap( spacing: 8, runSpacing: 8, children: _buildActionButtons(context), ), ], ), ); } List _buildActionButtons(BuildContext context) { List buttons = []; switch (commande.statut) { case StatutCommande.enAttente: buttons.addAll([ _buildActionButton( label: 'Confirmer', icon: Icons.check_circle, color: Colors.blue, onPressed: () => _showConfirmDialog( context, 'Confirmer la commande', 'Êtes-vous sûr de vouloir confirmer cette commande?', () => onStatutChanged(commande.id!, StatutCommande.confirmee), ), ), _buildActionButton( label: 'Annuler', icon: Icons.cancel, color: Colors.red, onPressed: () => _showConfirmDialog( context, 'Annuler la commande', 'Êtes-vous sûr de vouloir annuler cette commande?', () => onStatutChanged(commande.id!, StatutCommande.annulee), ), ), ]); break; case StatutCommande.confirmee: buttons.addAll([ _buildActionButton( label: 'Préparer', icon: Icons.settings, color: Colors.amber, onPressed: () => _showConfirmDialog( context, 'Marquer en préparation', 'La commande va être marquée comme étant en cours de préparation.', () => onStatutChanged(commande.id!, StatutCommande.enPreparation), ), ), _buildActionButton( label: 'Annuler', icon: Icons.cancel, color: Colors.red, onPressed: () => _showConfirmDialog( context, 'Annuler la commande', 'Êtes-vous sûr de vouloir annuler cette commande?', () => onStatutChanged(commande.id!, StatutCommande.annulee), ), ), ]); break; case StatutCommande.enPreparation: buttons.addAll([ _buildActionButton( label: 'Expédier', icon: Icons.local_shipping, color: Colors.purple, onPressed: () => _showConfirmDialog( context, 'Expédier la commande', 'La commande va être marquée comme expédiée.', () => onStatutChanged(commande.id!, StatutCommande.expediee), ), ), _buildActionButton( label: 'Annuler', icon: Icons.cancel, color: Colors.red, onPressed: () => _showConfirmDialog( context, 'Annuler la commande', 'Êtes-vous sûr de vouloir annuler cette commande?', () => onStatutChanged(commande.id!, StatutCommande.annulee), ), ), ]); break; case StatutCommande.expediee: buttons.add( _buildActionButton( label: 'Marquer livrée', icon: Icons.check_circle, color: Colors.green, onPressed: () => _showConfirmDialog( context, 'Marquer comme livrée', 'La commande va être marquée comme livrée.', () => onStatutChanged(commande.id!, StatutCommande.livree), ), ), ); break; case StatutCommande.livree: buttons.add( Container( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), decoration: BoxDecoration( color: Colors.green.shade100, borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.green.shade300), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.check_circle, color: Colors.green.shade600, size: 16), const SizedBox(width: 8), Text( 'Commande livrée', style: TextStyle( color: Colors.green.shade700, fontWeight: FontWeight.w600, ), ), ], ), ), ); break; case StatutCommande.annulee: buttons.add( Container( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), decoration: BoxDecoration( color: Colors.red.shade100, borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.red.shade300), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.cancel, color: Colors.red.shade600, size: 16), const SizedBox(width: 8), Text( 'Commande annulée', style: TextStyle( color: Colors.red.shade700, fontWeight: FontWeight.w600, ), ), ], ), ), ); break; } return buttons; } Widget _buildActionButton({ required String label, required IconData icon, required Color color, required VoidCallback onPressed, }) { return ElevatedButton.icon( onPressed: onPressed, icon: Icon(icon, size: 16), label: Text(label), style: ElevatedButton.styleFrom( backgroundColor: color, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), elevation: 2, ), ); } void _showConfirmDialog( BuildContext context, String title, String content, VoidCallback onConfirm, ) { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), title: Row( children: [ Icon( Icons.help_outline, color: Colors.blue.shade600, ), const SizedBox(width: 8), Text( title, style: const TextStyle(fontSize: 18), ), ], ), content: Text(content), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: Text( 'Annuler', style: TextStyle(color: Colors.grey.shade600), ), ), ElevatedButton( onPressed: () { Navigator.of(context).pop(); onConfirm(); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.blue.shade600, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: const Text('Confirmer'), ), ], ); }, ); } }