|
|
@ -35,28 +35,28 @@ class _CaisseScreenState extends State<CaisseScreen> { |
|
|
name: 'MVola', |
|
|
name: 'MVola', |
|
|
description: 'Paiement mobile MVola', |
|
|
description: 'Paiement mobile MVola', |
|
|
icon: Icons.phone, |
|
|
icon: Icons.phone, |
|
|
color: Color(0xFF4285F4), |
|
|
color: Color(0xFF28A745), |
|
|
), |
|
|
), |
|
|
const PaymentMethod( |
|
|
const PaymentMethod( |
|
|
id: 'orange_money', |
|
|
id: 'orange_money', |
|
|
name: 'Orange Money', |
|
|
name: 'Orange Money', |
|
|
description: 'Paiement mobile Orange Money', |
|
|
description: 'Paiement mobile Orange Money', |
|
|
icon: Icons.phone, |
|
|
icon: Icons.phone, |
|
|
color: Color(0xFF4285F4), |
|
|
color: Color(0xFFFF9500), |
|
|
), |
|
|
), |
|
|
const PaymentMethod( |
|
|
const PaymentMethod( |
|
|
id: 'carte', |
|
|
id: 'carte', |
|
|
name: 'Carte Bancaire', |
|
|
name: 'Carte Bancaire', |
|
|
description: 'Paiement par carte', |
|
|
description: 'Paiement par carte', |
|
|
icon: Icons.credit_card, |
|
|
icon: Icons.credit_card, |
|
|
color: Color(0xFF28A745), |
|
|
color: Color(0xFF4285F4), |
|
|
), |
|
|
), |
|
|
const PaymentMethod( |
|
|
const PaymentMethod( |
|
|
id: 'especes', |
|
|
id: 'especes', |
|
|
name: 'Espèces', |
|
|
name: 'Espèces', |
|
|
description: 'Paiement en liquide', |
|
|
description: 'Paiement en liquide', |
|
|
icon: Icons.attach_money, |
|
|
icon: Icons.attach_money, |
|
|
color: Color(0xFFFF9500), |
|
|
color: Color(0xFFFFEB3B), |
|
|
), |
|
|
), |
|
|
]; |
|
|
]; |
|
|
|
|
|
|
|
|
@ -332,28 +332,118 @@ class _CaisseScreenState extends State<CaisseScreen> { |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Widget _buildPaymentMethods() { |
|
|
|
|
|
return Column( |
|
|
Widget _buildPaymentSection() { |
|
|
|
|
|
double montantDonne = 0.0; |
|
|
|
|
|
double rendu = 0.0; |
|
|
|
|
|
TextEditingController montantController = TextEditingController(); |
|
|
|
|
|
|
|
|
|
|
|
return StatefulBuilder( |
|
|
|
|
|
builder: (context, setState) { |
|
|
|
|
|
return Row( |
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
|
|
children: [ |
|
|
|
|
|
// 🔵 Colonne gauche : méthodes de paiement |
|
|
|
|
|
Expanded( |
|
|
|
|
|
flex: 1, |
|
|
|
|
|
child: Column( |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
children: [ |
|
|
children: [ |
|
|
const Text( |
|
|
const Text( |
|
|
'Méthode de paiement', |
|
|
'Méthode de paiement', |
|
|
style: TextStyle( |
|
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), |
|
|
fontSize: 18, |
|
|
), |
|
|
fontWeight: FontWeight.bold, |
|
|
const SizedBox(height: 16), |
|
|
color: Colors.black87, |
|
|
...paymentMethods.map((method) { |
|
|
|
|
|
final isSelected = selectedPaymentMethod?.id == method.id; |
|
|
|
|
|
return _buildPaymentMethodCard(method, isSelected); // 🔹 plus besoin de StatefulBuilder |
|
|
|
|
|
}).toList(), |
|
|
|
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
|
|
|
|
|
|
const SizedBox(height: 16), |
|
|
|
|
|
|
|
|
|
|
|
...paymentMethods.map((method) => _buildPaymentMethodCard(method)), |
|
|
const SizedBox(width: 90), |
|
|
|
|
|
|
|
|
|
|
|
// 🟢 Colonne droite : saisie montant et rendu |
|
|
|
|
|
Expanded( |
|
|
|
|
|
flex: 1, |
|
|
|
|
|
child: Column( |
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
|
|
children: [ |
|
|
|
|
|
Text( |
|
|
|
|
|
'Montant à payer :', |
|
|
|
|
|
style: const TextStyle( |
|
|
|
|
|
fontWeight: FontWeight.bold, fontSize: 16), |
|
|
|
|
|
), |
|
|
|
|
|
const SizedBox(height: 8), |
|
|
|
|
|
Text( |
|
|
|
|
|
'${NumberFormat("#,##0.00", "fr_FR").format(commande?.totalTtc ?? 0)} MGA', |
|
|
|
|
|
style: const TextStyle( |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
|
|
fontSize: 20, |
|
|
|
|
|
color: Color(0xFF28A745)), |
|
|
|
|
|
), |
|
|
|
|
|
const SizedBox(height: 24), |
|
|
|
|
|
TextField( |
|
|
|
|
|
controller: montantController, |
|
|
|
|
|
keyboardType: TextInputType.number, |
|
|
|
|
|
decoration: const InputDecoration( |
|
|
|
|
|
labelText: "Montant donné par le client", |
|
|
|
|
|
border: OutlineInputBorder(), |
|
|
|
|
|
), |
|
|
|
|
|
onChanged: (value) { |
|
|
|
|
|
setState(() { |
|
|
|
|
|
montantDonne = double.tryParse(value) ?? 0.0; |
|
|
|
|
|
rendu = montantDonne - (commande?.totalTtc ?? 0.0); |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
), |
|
|
|
|
|
const SizedBox(height: 24), |
|
|
|
|
|
Text( |
|
|
|
|
|
'Rendu :', |
|
|
|
|
|
style: const TextStyle( |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
|
|
fontSize: 16, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
const SizedBox(height: 8), |
|
|
|
|
|
Container( |
|
|
|
|
|
padding: const EdgeInsets.symmetric( |
|
|
|
|
|
horizontal: 16, vertical: 12), |
|
|
|
|
|
decoration: BoxDecoration( |
|
|
|
|
|
color: rendu >= 0 ? Colors.green[50] : Colors.red[50], |
|
|
|
|
|
borderRadius: BorderRadius.circular(12), |
|
|
|
|
|
), |
|
|
|
|
|
child: Text( |
|
|
|
|
|
'${rendu >= 0 ? NumberFormat("#,##0.00", "fr_FR").format(rendu) : "0"} MGA', |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
|
|
fontSize: 24, // rendu plus grand |
|
|
|
|
|
color: rendu >= 0 ? Colors.green : Colors.red, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
if (rendu < 0) |
|
|
|
|
|
const Padding( |
|
|
|
|
|
padding: EdgeInsets.only(top: 8.0), |
|
|
|
|
|
child: Text( |
|
|
|
|
|
"Montant insuffisant", |
|
|
|
|
|
style: TextStyle(color: Colors.red), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
], |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
], |
|
|
], |
|
|
); |
|
|
); |
|
|
} |
|
|
}, |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
Widget _buildPaymentMethodCard(PaymentMethod method) { |
|
|
|
|
|
final isSelected = selectedPaymentMethod?.id == method.id; |
|
|
// Modification de _buildPaymentMethodCard pour accepter setState de la StatefulBuilder |
|
|
|
|
|
Widget _buildPaymentMethodCard(PaymentMethod method, bool isSelected) { |
|
|
final amount = commande?.totalTtc ?? 0.0; |
|
|
final amount = commande?.totalTtc ?? 0.0; |
|
|
|
|
|
|
|
|
return Container( |
|
|
return Container( |
|
|
@ -363,7 +453,7 @@ class _CaisseScreenState extends State<CaisseScreen> { |
|
|
child: InkWell( |
|
|
child: InkWell( |
|
|
onTap: () { |
|
|
onTap: () { |
|
|
setState(() { |
|
|
setState(() { |
|
|
selectedPaymentMethod = method; |
|
|
selectedPaymentMethod = method; // 🔹 setState global |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
borderRadius: BorderRadius.circular(12), |
|
|
borderRadius: BorderRadius.circular(12), |
|
|
@ -403,9 +493,7 @@ class _CaisseScreenState extends State<CaisseScreen> { |
|
|
size: 24, |
|
|
size: 24, |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
|
|
|
|
|
|
const SizedBox(width: 16), |
|
|
const SizedBox(width: 16), |
|
|
|
|
|
|
|
|
Expanded( |
|
|
Expanded( |
|
|
child: Column( |
|
|
child: Column( |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
@ -431,24 +519,18 @@ class _CaisseScreenState extends State<CaisseScreen> { |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
|
|
|
|
|
|
const SizedBox(width: 16), |
|
|
|
|
|
|
|
|
|
|
|
Icon( |
|
|
Icon( |
|
|
isSelected ? Icons.check_circle : Icons.radio_button_unchecked, |
|
|
isSelected ? Icons.check_circle : Icons.radio_button_unchecked, |
|
|
color: isSelected ? method.color : Colors.white, |
|
|
color: isSelected ? method.color : Colors.white, |
|
|
size: 22, |
|
|
size: 22, |
|
|
), |
|
|
), |
|
|
|
|
|
|
|
|
const SizedBox(width: 8), |
|
|
const SizedBox(width: 8), |
|
|
|
|
|
|
|
|
Text( |
|
|
Text( |
|
|
'${NumberFormat("#,##0.00", "fr_FR").format(amount)} MGA', |
|
|
'${NumberFormat("#,##0.00", "fr_FR").format(amount)} MGA', |
|
|
style: TextStyle( |
|
|
style: TextStyle( |
|
|
color: isSelected ? Colors.black87 : Colors.white, |
|
|
color: isSelected ? Colors.black87 : Colors.white, |
|
|
fontSize: 16, |
|
|
fontSize: 16, |
|
|
fontWeight: FontWeight.bold, |
|
|
fontWeight: FontWeight.bold), |
|
|
), |
|
|
|
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
@ -459,6 +541,9 @@ class _CaisseScreenState extends State<CaisseScreen> { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Widget _buildPaymentButton() { |
|
|
Widget _buildPaymentButton() { |
|
|
final canPay = selectedPaymentMethod != null && !isProcessingPayment; |
|
|
final canPay = selectedPaymentMethod != null && !isProcessingPayment; |
|
|
|
|
|
|
|
|
@ -600,14 +685,15 @@ class _CaisseScreenState extends State<CaisseScreen> { |
|
|
|
|
|
|
|
|
const SizedBox(height: 32), |
|
|
const SizedBox(height: 32), |
|
|
|
|
|
|
|
|
_buildPaymentMethods(), |
|
|
_buildPaymentSection(), // <-- ici on met le widget avec 2 colonnes |
|
|
|
|
|
|
|
|
_buildPaymentButton(), |
|
|
_buildPaymentButton(), |
|
|
|
|
|
|
|
|
const SizedBox(height: 20), |
|
|
const SizedBox(height: 20), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
|
|
|
|
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|