// pages/caisse_screen.dart import 'package:flutter/material.dart'; import 'package:itrimobe/pages/facture_screen.dart'; import '../models/command_detail.dart'; import '../models/payment_method.dart'; import '../services/restaurant_api_service.dart'; import 'package:intl/intl.dart'; class CaisseScreen extends StatefulWidget { final String commandeId; final int tableNumber; const CaisseScreen({ super.key, required this.commandeId, required this.tableNumber, }); @override _CaisseScreenState createState() => _CaisseScreenState(); } class _CaisseScreenState extends State { CommandeDetail? commande; PaymentMethod? selectedPaymentMethod; bool isLoading = true; bool isProcessingPayment = false; final List paymentMethods = [ const PaymentMethod( id: 'mvola', name: 'MVola', description: 'Paiement mobile MVola', icon: Icons.phone, color: Color(0xFF4285F4), ), const PaymentMethod( id: 'orange_money', name: 'Orange Money', description: 'Paiement mobile Orange Money', icon: Icons.phone, color: Color(0xFF4285F4), ), const PaymentMethod( id: 'carte', name: 'Carte Bancaire', description: 'Paiement par carte', icon: Icons.credit_card, color: Color(0xFF28A745), ), const PaymentMethod( id: 'especes', name: 'Espèces', description: 'Paiement en liquide', icon: Icons.attach_money, color: Color(0xFFFF9500), ), ]; @override void initState() { super.initState(); _loadCommandeDetails(); } Future _loadCommandeDetails() async { setState(() => isLoading = true); try { final result = await RestaurantApiService.getCommandeDetails( widget.commandeId, ); setState(() { commande = result; isLoading = false; }); } catch (e) { setState(() => isLoading = false); _showErrorDialog( 'Erreur lors du chargement des détails de la commande: $e', ); } } // Dans caisse_screen.dart, modifiez la méthode _processPayment Future _processPayment() async { if (selectedPaymentMethod == null || commande == null) return; setState(() => isProcessingPayment = true); try { final success = await RestaurantApiService.processPayment( commandeId: widget.commandeId, paymentMethodId: selectedPaymentMethod!.id, amount: commande!.totalTtc, ); if (success) { final updateSuccess = await RestaurantApiService.updateCommandeStatus( commandeId: widget.commandeId, newStatus: 'payee', ); if (!updateSuccess) { _showErrorDialog("Paiement effectué, mais échec lors de la mise à jour du statut."); return; } // 🔄 Redirige vers la facture Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => FactureScreen( commande: commande!, paymentMethod: selectedPaymentMethod!.id, ), ), ); } else { _showErrorDialog('Le paiement a échoué. Veuillez réessayer.'); } } catch (e) { _showErrorDialog('Erreur lors du traitement du paiement: $e'); } finally { if (mounted) { setState(() => isProcessingPayment = false); } } } void _showErrorDialog(String message) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Erreur'), content: Text(message), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('OK'), ), ], ), ); } void _showSuccessDialog() { showDialog( context: context, barrierDismissible: false, builder: (context) => AlertDialog( title: const Row( children: [ Icon(Icons.check_circle, color: Color(0xFF28A745), size: 28), SizedBox(width: 12), Text('Paiement réussi'), ], ), content: Text( 'Le paiement de ${NumberFormat("#,##0.00", "fr_FR").format(commande!.totalTtc)} MGA a été traité avec succès via ${selectedPaymentMethod!.name}.', ), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); // Fermer le dialog Navigator.of( context, ).pop(true); // Retourner à la page précédente avec succès }, child: const Text('Fermer'), ), ], ), ); } Widget _buildCommandeHeader() { if (commande == null) return const SizedBox.shrink(); return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.grey[200]!), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Commande #${commande!.numeroCommande}', style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black87, ), ), Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6, ), decoration: BoxDecoration( color: Colors.blue[50], borderRadius: BorderRadius.circular(20), border: Border.all(color: Colors.blue[200]!), ), child: Text( 'Table ${widget.tableNumber}', style: TextStyle( color: Colors.blue[700], fontSize: 12, fontWeight: FontWeight.w600, ), ), ), ], ), const SizedBox(height: 16), _buildCommandeItems(), const SizedBox(height: 16), const Divider(), const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Total:', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black87, ), ), Text( '${NumberFormat("#,##0.00", "fr_FR").format(commande!.totalTtc)} MGA', style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Color(0xFF28A745), ), ), ], ), ], ), ); } Widget _buildCommandeItems() { if (commande?.items.isEmpty ?? true) { return const Text('Aucun article'); } return Column( children: commande!.items.map((item) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '${item.quantite}× ${item.menuNom}', style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w500, ), ), if (item.menuDescription != null && item.menuDescription!.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 2), child: Text( item.menuDescription!, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), if (item.hasComments) Padding( padding: const EdgeInsets.only(top: 2), child: Text( 'Note: ${item.commentaires}', style: TextStyle( fontSize: 12, color: Colors.orange[700], fontStyle: FontStyle.italic, ), ), ), ], ), ), const SizedBox(width: 12), Text( '${NumberFormat("#,##0.00", "fr_FR").format(item.totalItem)} MGA', style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, ), ), ], ), ); }).toList(), ); } Widget _buildPaymentMethods() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Méthode de paiement', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black87, ), ), const SizedBox(height: 16), ...paymentMethods.map((method) => _buildPaymentMethodCard(method)), ], ); } Widget _buildPaymentMethodCard(PaymentMethod method) { final isSelected = selectedPaymentMethod?.id == method.id; final amount = commande?.totalTtc ?? 0.0; return Container( margin: const EdgeInsets.only(bottom: 12), child: Material( color: Colors.transparent, child: InkWell( onTap: () { setState(() { selectedPaymentMethod = method; }); }, borderRadius: BorderRadius.circular(12), child: Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: method.color, borderRadius: BorderRadius.circular(12), border: isSelected ? Border.all(color: Colors.white, width: 3) : null, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Row( children: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(8), ), child: Icon(method.icon, color: Colors.white, size: 24), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( method.name, style: const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4), Text( method.description, style: TextStyle( color: Colors.white.withOpacity(0.9), fontSize: 13, ), ), ], ), ), const SizedBox(width: 16), Text( '${NumberFormat("#,##0.00", "fr_FR").format(amount)} MGA', style: const TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold, ), ), ], ), ), ), ), ); } Widget _buildPaymentButton() { final canPay = selectedPaymentMethod != null && !isProcessingPayment; return Container( width: double.infinity, margin: const EdgeInsets.only(top: 20), child: ElevatedButton( onPressed: canPay ? _processPayment : null, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF28A745), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), elevation: 2, ), child: isProcessingPayment ? const Row( mainAxisSize: MainAxisSize.min, children: [ SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ), SizedBox(width: 12), Text( 'Traitement en cours...', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), ], ) : Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.payment, size: 20), const SizedBox(width: 8), Text( selectedPaymentMethod != null ? 'Payer ${NumberFormat("#,##0.00", "fr_FR").format(commande?.totalTtc)} MGA' : 'Sélectionnez une méthode de paiement', style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), ], ), ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( backgroundColor: Colors.white, elevation: 0, leading: IconButton( icon: const Icon(Icons.arrow_back, color: Colors.black87), onPressed: () => Navigator.of(context).pop(), ), title: const Text( 'Caisse', style: TextStyle( color: Colors.black87, fontSize: 20, fontWeight: FontWeight.bold, ), ), centerTitle: true, ), body: isLoading ? const Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ CircularProgressIndicator( valueColor: AlwaysStoppedAnimation( Color(0xFF28A745), ), ), SizedBox(height: 16), Text( 'Chargement des détails...', style: TextStyle(fontSize: 14, color: Colors.grey), ), ], ), ) : commande == null ? Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon( Icons.error_outline, size: 64, color: Colors.red, ), const SizedBox(height: 16), const Text( 'Impossible de charger la commande', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 8), Text( 'Commande #${widget.commandeId}', style: TextStyle(fontSize: 14, color: Colors.grey[600]), ), const SizedBox(height: 20), ElevatedButton( onPressed: _loadCommandeDetails, child: const Text('Réessayer'), ), ], ), ) : SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildCommandeHeader(), const SizedBox(height: 32), _buildPaymentMethods(), _buildPaymentButton(), const SizedBox(height: 20), ], ), ), ); } }