|
|
@ -77,7 +77,10 @@ class _CartPageState extends State<CartPage> { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
double _calculateTotal() { |
|
|
double _calculateTotal() { |
|
|
return _cartItems.fold(0.0, (sum, item) => sum + (item.prix * item.quantity)); |
|
|
return _cartItems.fold( |
|
|
|
|
|
0.0, |
|
|
|
|
|
(sum, item) => sum + (item.prix * item.quantity), |
|
|
|
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int _getTotalArticles() { |
|
|
int _getTotalArticles() { |
|
|
@ -113,30 +116,33 @@ class _CartPageState extends State<CartPage> { |
|
|
actions: [ |
|
|
actions: [ |
|
|
TextButton( |
|
|
TextButton( |
|
|
onPressed: () => Navigator.of(context).pop(), |
|
|
onPressed: () => Navigator.of(context).pop(), |
|
|
child: Text( |
|
|
child: Text('Annuler', style: TextStyle(color: Colors.grey[600])), |
|
|
'Annuler', |
|
|
|
|
|
style: TextStyle(color: Colors.grey[600]), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
), |
|
|
ElevatedButton( |
|
|
ElevatedButton( |
|
|
onPressed: _isValidating ? null : () { |
|
|
onPressed: |
|
|
Navigator.of(context).pop(); |
|
|
_isValidating |
|
|
_validateOrder(); |
|
|
? null |
|
|
}, |
|
|
: () { |
|
|
|
|
|
Navigator.of(context).pop(); |
|
|
|
|
|
_validateOrder(); |
|
|
|
|
|
}, |
|
|
style: ElevatedButton.styleFrom( |
|
|
style: ElevatedButton.styleFrom( |
|
|
backgroundColor: Colors.green[700], |
|
|
backgroundColor: Colors.green[700], |
|
|
foregroundColor: Colors.white, |
|
|
foregroundColor: Colors.white, |
|
|
), |
|
|
), |
|
|
child: _isValidating |
|
|
child: |
|
|
? SizedBox( |
|
|
_isValidating |
|
|
width: 16, |
|
|
? SizedBox( |
|
|
height: 16, |
|
|
width: 16, |
|
|
child: CircularProgressIndicator( |
|
|
height: 16, |
|
|
strokeWidth: 2, |
|
|
child: CircularProgressIndicator( |
|
|
valueColor: AlwaysStoppedAnimation<Color>(Colors.white), |
|
|
strokeWidth: 2, |
|
|
), |
|
|
valueColor: AlwaysStoppedAnimation<Color>( |
|
|
) |
|
|
Colors.white, |
|
|
: Text('Valider'), |
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
) |
|
|
|
|
|
: Text('Valider'), |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
); |
|
|
); |
|
|
@ -157,29 +163,36 @@ class _CartPageState extends State<CartPage> { |
|
|
"reservation_id": 1, // Peut être null si pas de réservation |
|
|
"reservation_id": 1, // Peut être null si pas de réservation |
|
|
"serveur": "Serveur par défaut", // Valeur par défaut comme demandé |
|
|
"serveur": "Serveur par défaut", // Valeur par défaut comme demandé |
|
|
"commentaires": _getOrderComments(), |
|
|
"commentaires": _getOrderComments(), |
|
|
"items": _cartItems.map((item) => { |
|
|
"items": |
|
|
"menu_id": item.id, |
|
|
_cartItems |
|
|
"quantite": item.quantity, |
|
|
.map( |
|
|
"commentaires": item.notes.isNotEmpty ? item.notes : null, |
|
|
(item) => { |
|
|
}).toList(), |
|
|
"menu_id": item.id, |
|
|
|
|
|
"quantite": item.quantity, |
|
|
|
|
|
"commentaires": item.notes.isNotEmpty ? item.notes : null, |
|
|
|
|
|
}, |
|
|
|
|
|
) |
|
|
|
|
|
.toList(), |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// Appel API pour créer la commande |
|
|
// Appel API pour créer la commande |
|
|
final response = await http.post( |
|
|
final response = await http.post( |
|
|
Uri.parse('https://restaurant.careeracademy.mg/api/commandes'), // Remplacez par votre URL d'API |
|
|
Uri.parse( |
|
|
headers: { |
|
|
'https://restaurant.careeracademy.mg/api/commandes', |
|
|
'Content-Type': 'application/json', |
|
|
), // Remplacez par votre URL d'API |
|
|
}, |
|
|
headers: {'Content-Type': 'application/json'}, |
|
|
body: json.encode(orderData), |
|
|
body: json.encode(orderData), |
|
|
); |
|
|
); |
|
|
print(orderData); |
|
|
print('response body: ${response.body}'); |
|
|
|
|
|
|
|
|
if (response.statusCode == 200 || response.statusCode == 201) { |
|
|
if (response.statusCode == 200 || response.statusCode == 201) { |
|
|
// Succès |
|
|
// Succès |
|
|
_showSuccessDialog(); |
|
|
_showSuccessDialog(); |
|
|
} else { |
|
|
} else { |
|
|
// Erreur |
|
|
// Erreur |
|
|
_showErrorDialog('Erreur lors de l\'enregistrement de la commande (${response.statusCode})'); |
|
|
_showErrorDialog( |
|
|
|
|
|
'Erreur lors de l\'enregistrement de la commande (${response.statusCode})', |
|
|
|
|
|
); |
|
|
} |
|
|
} |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
_showErrorDialog('Erreur de connexion: $e'); |
|
|
_showErrorDialog('Erreur de connexion: $e'); |
|
|
@ -192,10 +205,11 @@ class _CartPageState extends State<CartPage> { |
|
|
|
|
|
|
|
|
String _getOrderComments() { |
|
|
String _getOrderComments() { |
|
|
// Concaténer toutes les notes des articles pour les commentaires généraux |
|
|
// Concaténer toutes les notes des articles pour les commentaires généraux |
|
|
List<String> allNotes = _cartItems |
|
|
List<String> allNotes = |
|
|
.where((item) => item.notes.isNotEmpty) |
|
|
_cartItems |
|
|
.map((item) => '${item.nom}: ${item.notes}') |
|
|
.where((item) => item.notes.isNotEmpty) |
|
|
.toList(); |
|
|
.map((item) => '${item.nom}: ${item.notes}') |
|
|
|
|
|
.toList(); |
|
|
|
|
|
|
|
|
return allNotes.join('; '); |
|
|
return allNotes.join('; '); |
|
|
} |
|
|
} |
|
|
@ -213,7 +227,9 @@ class _CartPageState extends State<CartPage> { |
|
|
Text('Commande validée'), |
|
|
Text('Commande validée'), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
content: Text('Votre commande a été envoyée en cuisine avec succès !'), |
|
|
content: Text( |
|
|
|
|
|
'Votre commande a été envoyée en cuisine avec succès !', |
|
|
|
|
|
), |
|
|
actions: [ |
|
|
actions: [ |
|
|
ElevatedButton( |
|
|
ElevatedButton( |
|
|
onPressed: () { |
|
|
onPressed: () { |
|
|
@ -281,299 +297,303 @@ class _CartPageState extends State<CartPage> { |
|
|
onPressed: () => Navigator.pop(context), |
|
|
onPressed: () => Navigator.pop(context), |
|
|
child: Text( |
|
|
child: Text( |
|
|
'Retour au menu', |
|
|
'Retour au menu', |
|
|
style: TextStyle( |
|
|
style: TextStyle(color: Colors.black, fontSize: 16), |
|
|
color: Colors.black, |
|
|
|
|
|
fontSize: 16, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
SizedBox(width: 16), |
|
|
SizedBox(width: 16), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
body: _cartItems.isEmpty |
|
|
body: |
|
|
? Center( |
|
|
_cartItems.isEmpty |
|
|
child: Column( |
|
|
? Center( |
|
|
mainAxisAlignment: MainAxisAlignment.center, |
|
|
child: Column( |
|
|
children: [ |
|
|
mainAxisAlignment: MainAxisAlignment.center, |
|
|
Icon( |
|
|
children: [ |
|
|
Icons.shopping_cart_outlined, |
|
|
Icon( |
|
|
size: 80, |
|
|
Icons.shopping_cart_outlined, |
|
|
color: Colors.grey[400], |
|
|
size: 80, |
|
|
), |
|
|
color: Colors.grey[400], |
|
|
SizedBox(height: 16), |
|
|
|
|
|
Text( |
|
|
|
|
|
'Votre panier est vide', |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
fontSize: 18, |
|
|
|
|
|
color: Colors.grey[600], |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
SizedBox(height: 16), |
|
|
], |
|
|
Text( |
|
|
), |
|
|
'Votre panier est vide', |
|
|
) |
|
|
style: TextStyle(fontSize: 18, color: Colors.grey[600]), |
|
|
: Column( |
|
|
|
|
|
children: [ |
|
|
|
|
|
// Header avec infos table |
|
|
|
|
|
Container( |
|
|
|
|
|
width: double.infinity, |
|
|
|
|
|
padding: EdgeInsets.all(20), |
|
|
|
|
|
color: Colors.white, |
|
|
|
|
|
child: Text( |
|
|
|
|
|
'Table ${widget.tableId} • ${widget.personne} personne${widget.personne > 1 ? 's' : ''}', |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
fontSize: 16, |
|
|
|
|
|
color: Colors.grey[600], |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
), |
|
|
), |
|
|
|
|
|
) |
|
|
|
|
|
: Column( |
|
|
|
|
|
children: [ |
|
|
|
|
|
// Header avec infos table |
|
|
|
|
|
Container( |
|
|
|
|
|
width: double.infinity, |
|
|
|
|
|
padding: EdgeInsets.all(20), |
|
|
|
|
|
color: Colors.white, |
|
|
|
|
|
child: Text( |
|
|
|
|
|
'Table ${widget.tableId} • ${widget.personne} personne${widget.personne > 1 ? 's' : ''}', |
|
|
|
|
|
style: TextStyle(fontSize: 16, color: Colors.grey[600]), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
// Liste des articles |
|
|
// Liste des articles |
|
|
Expanded( |
|
|
Expanded( |
|
|
child: ListView.separated( |
|
|
child: ListView.separated( |
|
|
padding: EdgeInsets.all(16), |
|
|
padding: EdgeInsets.all(16), |
|
|
itemCount: _cartItems.length, |
|
|
itemCount: _cartItems.length, |
|
|
separatorBuilder: (context, index) => SizedBox(height: 12), |
|
|
separatorBuilder: |
|
|
itemBuilder: (context, index) { |
|
|
(context, index) => SizedBox(height: 12), |
|
|
final item = _cartItems[index]; |
|
|
itemBuilder: (context, index) { |
|
|
return Container( |
|
|
final item = _cartItems[index]; |
|
|
padding: EdgeInsets.all(16), |
|
|
return Container( |
|
|
decoration: BoxDecoration( |
|
|
padding: EdgeInsets.all(16), |
|
|
color: Colors.white, |
|
|
decoration: BoxDecoration( |
|
|
borderRadius: BorderRadius.circular(12), |
|
|
color: Colors.white, |
|
|
boxShadow: [ |
|
|
borderRadius: BorderRadius.circular(12), |
|
|
BoxShadow( |
|
|
boxShadow: [ |
|
|
color: Colors.black.withOpacity(0.05), |
|
|
BoxShadow( |
|
|
blurRadius: 5, |
|
|
color: Colors.black.withOpacity(0.05), |
|
|
offset: Offset(0, 2), |
|
|
blurRadius: 5, |
|
|
), |
|
|
offset: Offset(0, 2), |
|
|
], |
|
|
), |
|
|
), |
|
|
], |
|
|
child: Column( |
|
|
), |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
child: Column( |
|
|
children: [ |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
Row( |
|
|
children: [ |
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
Row( |
|
|
children: [ |
|
|
mainAxisAlignment: |
|
|
Expanded( |
|
|
MainAxisAlignment.spaceBetween, |
|
|
child: Text( |
|
|
children: [ |
|
|
item.nom, |
|
|
Expanded( |
|
|
style: TextStyle( |
|
|
child: Text( |
|
|
fontSize: 18, |
|
|
item.nom, |
|
|
fontWeight: FontWeight.bold, |
|
|
style: TextStyle( |
|
|
|
|
|
fontSize: 18, |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
IconButton( |
|
|
IconButton( |
|
|
onPressed: () => _removeItem(index), |
|
|
onPressed: () => _removeItem(index), |
|
|
icon: Icon( |
|
|
icon: Icon( |
|
|
Icons.delete_outline, |
|
|
Icons.delete_outline, |
|
|
color: Colors.red, |
|
|
color: Colors.red, |
|
|
), |
|
|
|
|
|
constraints: BoxConstraints(), |
|
|
|
|
|
padding: EdgeInsets.zero, |
|
|
), |
|
|
), |
|
|
constraints: BoxConstraints(), |
|
|
], |
|
|
padding: EdgeInsets.zero, |
|
|
|
|
|
), |
|
|
|
|
|
], |
|
|
|
|
|
), |
|
|
|
|
|
Text( |
|
|
|
|
|
'${item.prix.toStringAsFixed(2)} € l\'unité', |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
fontSize: 14, |
|
|
|
|
|
color: Colors.grey[600], |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
|
|
|
if (item.notes.isNotEmpty) ...[ |
|
|
|
|
|
SizedBox(height: 8), |
|
|
|
|
|
Text( |
|
|
Text( |
|
|
'Notes: ${item.notes}', |
|
|
'${item.prix.toStringAsFixed(2)} € l\'unité', |
|
|
style: TextStyle( |
|
|
style: TextStyle( |
|
|
fontSize: 14, |
|
|
fontSize: 14, |
|
|
color: Colors.grey[600], |
|
|
color: Colors.grey[600], |
|
|
fontStyle: FontStyle.italic, |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
if (item.notes.isNotEmpty) ...[ |
|
|
SizedBox(height: 16), |
|
|
SizedBox(height: 8), |
|
|
Row( |
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
|
|
|
children: [ |
|
|
|
|
|
// Contrôles de quantité |
|
|
|
|
|
Row( |
|
|
|
|
|
children: [ |
|
|
|
|
|
IconButton( |
|
|
|
|
|
onPressed: () => _updateQuantity(index, item.quantity - 1), |
|
|
|
|
|
icon: Icon(Icons.remove), |
|
|
|
|
|
style: IconButton.styleFrom( |
|
|
|
|
|
backgroundColor: Colors.grey[200], |
|
|
|
|
|
minimumSize: Size(40, 40), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
SizedBox(width: 16), |
|
|
|
|
|
Text( |
|
|
|
|
|
item.quantity.toString(), |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
fontSize: 18, |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
SizedBox(width: 16), |
|
|
|
|
|
IconButton( |
|
|
|
|
|
onPressed: () => _updateQuantity(index, item.quantity + 1), |
|
|
|
|
|
icon: Icon(Icons.add), |
|
|
|
|
|
style: IconButton.styleFrom( |
|
|
|
|
|
backgroundColor: Colors.grey[200], |
|
|
|
|
|
minimumSize: Size(40, 40), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
], |
|
|
|
|
|
), |
|
|
|
|
|
// Prix total de l'article |
|
|
|
|
|
Text( |
|
|
Text( |
|
|
'${(item.prix * item.quantity).toStringAsFixed(2)} €', |
|
|
'Notes: ${item.notes}', |
|
|
style: TextStyle( |
|
|
style: TextStyle( |
|
|
fontSize: 18, |
|
|
fontSize: 14, |
|
|
fontWeight: FontWeight.bold, |
|
|
color: Colors.grey[600], |
|
|
color: Colors.green[700], |
|
|
fontStyle: FontStyle.italic, |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
SizedBox(height: 16), |
|
|
], |
|
|
Row( |
|
|
), |
|
|
mainAxisAlignment: |
|
|
); |
|
|
MainAxisAlignment.spaceBetween, |
|
|
}, |
|
|
children: [ |
|
|
|
|
|
// Contrôles de quantité |
|
|
|
|
|
Row( |
|
|
|
|
|
children: [ |
|
|
|
|
|
IconButton( |
|
|
|
|
|
onPressed: |
|
|
|
|
|
() => _updateQuantity( |
|
|
|
|
|
index, |
|
|
|
|
|
item.quantity - 1, |
|
|
|
|
|
), |
|
|
|
|
|
icon: Icon(Icons.remove), |
|
|
|
|
|
style: IconButton.styleFrom( |
|
|
|
|
|
backgroundColor: Colors.grey[200], |
|
|
|
|
|
minimumSize: Size(40, 40), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
SizedBox(width: 16), |
|
|
|
|
|
Text( |
|
|
|
|
|
item.quantity.toString(), |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
fontSize: 18, |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
SizedBox(width: 16), |
|
|
|
|
|
IconButton( |
|
|
|
|
|
onPressed: |
|
|
|
|
|
() => _updateQuantity( |
|
|
|
|
|
index, |
|
|
|
|
|
item.quantity + 1, |
|
|
|
|
|
), |
|
|
|
|
|
icon: Icon(Icons.add), |
|
|
|
|
|
style: IconButton.styleFrom( |
|
|
|
|
|
backgroundColor: Colors.grey[200], |
|
|
|
|
|
minimumSize: Size(40, 40), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
], |
|
|
|
|
|
), |
|
|
|
|
|
// Prix total de l'article |
|
|
|
|
|
Text( |
|
|
|
|
|
'${(item.prix * item.quantity).toStringAsFixed(2)} €', |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
fontSize: 18, |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
|
|
color: Colors.green[700], |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
], |
|
|
|
|
|
), |
|
|
|
|
|
], |
|
|
|
|
|
), |
|
|
|
|
|
); |
|
|
|
|
|
}, |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
// Récapitulatif |
|
|
// Récapitulatif |
|
|
Container( |
|
|
Container( |
|
|
padding: EdgeInsets.all(20), |
|
|
padding: EdgeInsets.all(20), |
|
|
decoration: BoxDecoration( |
|
|
decoration: BoxDecoration( |
|
|
color: Colors.white, |
|
|
color: Colors.white, |
|
|
border: Border( |
|
|
border: Border(top: BorderSide(color: Colors.grey[200]!)), |
|
|
top: BorderSide(color: Colors.grey[200]!), |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
child: Column( |
|
|
child: Column( |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
children: [ |
|
|
children: [ |
|
|
Text( |
|
|
Text( |
|
|
'Récapitulatif', |
|
|
'Récapitulatif', |
|
|
style: TextStyle( |
|
|
style: TextStyle( |
|
|
fontSize: 20, |
|
|
fontSize: 20, |
|
|
fontWeight: FontWeight.bold, |
|
|
fontWeight: FontWeight.bold, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
SizedBox(height: 16), |
|
|
|
|
|
Row( |
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
|
|
|
children: [ |
|
|
|
|
|
Text('Articles:', style: TextStyle(fontSize: 16)), |
|
|
|
|
|
Text( |
|
|
|
|
|
_getTotalArticles().toString(), |
|
|
|
|
|
style: TextStyle(fontSize: 16), |
|
|
|
|
|
), |
|
|
|
|
|
], |
|
|
|
|
|
), |
|
|
|
|
|
SizedBox(height: 8), |
|
|
|
|
|
Row( |
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
|
|
|
children: [ |
|
|
|
|
|
Text('Table:', style: TextStyle(fontSize: 16)), |
|
|
|
|
|
Text( |
|
|
|
|
|
widget.tableId.toString(), |
|
|
|
|
|
style: TextStyle(fontSize: 16), |
|
|
|
|
|
), |
|
|
), |
|
|
], |
|
|
), |
|
|
), |
|
|
SizedBox(height: 16), |
|
|
SizedBox(height: 8), |
|
|
Row( |
|
|
Row( |
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
children: [ |
|
|
children: [ |
|
|
Text('Articles:', style: TextStyle(fontSize: 16)), |
|
|
Text('Personnes:', style: TextStyle(fontSize: 16)), |
|
|
Text( |
|
|
Text( |
|
|
_getTotalArticles().toString(), |
|
|
widget.personne.toString(), |
|
|
style: TextStyle(fontSize: 16), |
|
|
style: TextStyle(fontSize: 16), |
|
|
|
|
|
), |
|
|
|
|
|
], |
|
|
|
|
|
), |
|
|
|
|
|
SizedBox(height: 16), |
|
|
|
|
|
Divider(), |
|
|
|
|
|
SizedBox(height: 8), |
|
|
|
|
|
Row( |
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
|
|
|
children: [ |
|
|
|
|
|
Text( |
|
|
|
|
|
'Total:', |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
fontSize: 18, |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
Text( |
|
|
), |
|
|
'${_calculateTotal().toStringAsFixed(2)} €', |
|
|
SizedBox(height: 8), |
|
|
style: TextStyle( |
|
|
Row( |
|
|
fontSize: 18, |
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
fontWeight: FontWeight.bold, |
|
|
children: [ |
|
|
|
|
|
Text('Table:', style: TextStyle(fontSize: 16)), |
|
|
|
|
|
Text( |
|
|
|
|
|
widget.tableId.toString(), |
|
|
|
|
|
style: TextStyle(fontSize: 16), |
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
SizedBox(height: 8), |
|
|
SizedBox(height: 20), |
|
|
Row( |
|
|
SizedBox( |
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
width: double.infinity, |
|
|
children: [ |
|
|
child: ElevatedButton( |
|
|
Text('Personnes:', style: TextStyle(fontSize: 16)), |
|
|
onPressed: _cartItems.isNotEmpty && !_isValidating |
|
|
Text( |
|
|
? _showConfirmationDialog |
|
|
widget.personne.toString(), |
|
|
: null, |
|
|
style: TextStyle(fontSize: 16), |
|
|
style: ElevatedButton.styleFrom( |
|
|
|
|
|
backgroundColor: Colors.green[700], |
|
|
|
|
|
foregroundColor: Colors.white, |
|
|
|
|
|
padding: EdgeInsets.symmetric(vertical: 16), |
|
|
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
|
|
borderRadius: BorderRadius.circular(12), |
|
|
|
|
|
), |
|
|
), |
|
|
disabledBackgroundColor: Colors.grey[300], |
|
|
], |
|
|
), |
|
|
), |
|
|
child: Row( |
|
|
SizedBox(height: 16), |
|
|
mainAxisAlignment: MainAxisAlignment.center, |
|
|
Divider(), |
|
|
children: [ |
|
|
SizedBox(height: 8), |
|
|
if (_isValidating) ...[ |
|
|
Row( |
|
|
SizedBox( |
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
width: 20, |
|
|
children: [ |
|
|
height: 20, |
|
|
Text( |
|
|
child: CircularProgressIndicator( |
|
|
'Total:', |
|
|
strokeWidth: 2, |
|
|
style: TextStyle( |
|
|
valueColor: AlwaysStoppedAnimation<Color>(Colors.white), |
|
|
fontSize: 18, |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
Text( |
|
|
|
|
|
'${_calculateTotal().toStringAsFixed(2)} €', |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
fontSize: 18, |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
], |
|
|
|
|
|
), |
|
|
|
|
|
SizedBox(height: 20), |
|
|
|
|
|
SizedBox( |
|
|
|
|
|
width: double.infinity, |
|
|
|
|
|
child: ElevatedButton( |
|
|
|
|
|
onPressed: |
|
|
|
|
|
_cartItems.isNotEmpty && !_isValidating |
|
|
|
|
|
? _showConfirmationDialog |
|
|
|
|
|
: null, |
|
|
|
|
|
style: ElevatedButton.styleFrom( |
|
|
|
|
|
backgroundColor: Colors.green[700], |
|
|
|
|
|
foregroundColor: Colors.white, |
|
|
|
|
|
padding: EdgeInsets.symmetric(vertical: 16), |
|
|
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
|
|
borderRadius: BorderRadius.circular(12), |
|
|
|
|
|
), |
|
|
|
|
|
disabledBackgroundColor: Colors.grey[300], |
|
|
|
|
|
), |
|
|
|
|
|
child: Row( |
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center, |
|
|
|
|
|
children: [ |
|
|
|
|
|
if (_isValidating) ...[ |
|
|
|
|
|
SizedBox( |
|
|
|
|
|
width: 20, |
|
|
|
|
|
height: 20, |
|
|
|
|
|
child: CircularProgressIndicator( |
|
|
|
|
|
strokeWidth: 2, |
|
|
|
|
|
valueColor: AlwaysStoppedAnimation<Color>( |
|
|
|
|
|
Colors.white, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
SizedBox(width: 8), |
|
|
SizedBox(width: 8), |
|
|
Text( |
|
|
Text( |
|
|
'Validation en cours...', |
|
|
'Validation en cours...', |
|
|
style: TextStyle( |
|
|
style: TextStyle( |
|
|
fontSize: 16, |
|
|
fontSize: 16, |
|
|
fontWeight: FontWeight.bold, |
|
|
fontWeight: FontWeight.bold, |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
] else ...[ |
|
|
] else ...[ |
|
|
Icon(Icons.check, size: 20), |
|
|
Icon(Icons.check, size: 20), |
|
|
SizedBox(width: 8), |
|
|
SizedBox(width: 8), |
|
|
Text( |
|
|
Text( |
|
|
'Valider la commande', |
|
|
'Valider la commande', |
|
|
style: TextStyle( |
|
|
style: TextStyle( |
|
|
fontSize: 16, |
|
|
fontSize: 16, |
|
|
fontWeight: FontWeight.bold, |
|
|
fontWeight: FontWeight.bold, |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
|
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|