Compare commits
3 Commits
d2b98f7bbb
...
48968a8ef8
| Author | SHA1 | Date | |
|---|---|---|---|
| 48968a8ef8 | |||
| 2bccb7a3b4 | |||
| 093238961f |
@ -1,4 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
class CartPage extends StatefulWidget {
|
class CartPage extends StatefulWidget {
|
||||||
final int tableId;
|
final int tableId;
|
||||||
@ -18,6 +20,7 @@ class CartPage extends StatefulWidget {
|
|||||||
|
|
||||||
class _CartPageState extends State<CartPage> {
|
class _CartPageState extends State<CartPage> {
|
||||||
List<CartItemModel> _cartItems = [];
|
List<CartItemModel> _cartItems = [];
|
||||||
|
bool _isValidating = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -81,21 +84,171 @@ class _CartPageState extends State<CartPage> {
|
|||||||
return _cartItems.fold(0, (sum, item) => sum + item.quantity);
|
return _cartItems.fold(0, (sum, item) => sum + item.quantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _validateOrder() {
|
void _showConfirmationDialog() {
|
||||||
// TODO: Implémenter la validation de commande
|
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: Text('Commande validée'),
|
title: Text(
|
||||||
content: Text('Votre commande a été envoyée en cuisine !'),
|
'Confirmer la commande',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('Êtes-vous sûr de vouloir valider cette commande ?'),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
'Récapitulatif:',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
Text('• Table: ${widget.tableId}'),
|
||||||
|
Text('• Personnes: ${widget.personne}'),
|
||||||
|
Text('• Articles: ${_getTotalArticles()}'),
|
||||||
|
Text('• Total: ${_calculateTotal().toStringAsFixed(2)} €'),
|
||||||
|
],
|
||||||
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text(
|
||||||
|
'Annuler',
|
||||||
|
style: TextStyle(color: Colors.grey[600]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: _isValidating ? null : () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
_validateOrder();
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: Colors.green[700],
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
),
|
||||||
|
child: _isValidating
|
||||||
|
? SizedBox(
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2,
|
||||||
|
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Text('Valider'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _validateOrder() async {
|
||||||
|
setState(() {
|
||||||
|
_isValidating = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Préparer les données de la commande
|
||||||
|
final orderData = {
|
||||||
|
"client_id": 1, // Valeur par défaut comme demandé
|
||||||
|
"table_id": widget.tableId,
|
||||||
|
"reservation_id": 1, // Peut être null si pas de réservation
|
||||||
|
"serveur": "Serveur par défaut", // Valeur par défaut comme demandé
|
||||||
|
"commentaires": _getOrderComments(),
|
||||||
|
"items": _cartItems.map((item) => {
|
||||||
|
"menu_id": item.id,
|
||||||
|
"quantite": item.quantity,
|
||||||
|
"commentaires": item.notes.isNotEmpty ? item.notes : null,
|
||||||
|
}).toList(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Appel API pour créer la commande
|
||||||
|
final response = await http.post(
|
||||||
|
Uri.parse('https://restaurant.careeracademy.mg/api/commandes'), // Remplacez par votre URL d'API
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: json.encode(orderData),
|
||||||
|
);
|
||||||
|
print(orderData);
|
||||||
|
|
||||||
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||||
|
// Succès
|
||||||
|
_showSuccessDialog();
|
||||||
|
} else {
|
||||||
|
// Erreur
|
||||||
|
_showErrorDialog('Erreur lors de l\'enregistrement de la commande (${response.statusCode})');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
_showErrorDialog('Erreur de connexion: $e');
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
_isValidating = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _getOrderComments() {
|
||||||
|
// Concaténer toutes les notes des articles pour les commentaires généraux
|
||||||
|
List<String> allNotes = _cartItems
|
||||||
|
.where((item) => item.notes.isNotEmpty)
|
||||||
|
.map((item) => '${item.nom}: ${item.notes}')
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return allNotes.join('; ');
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showSuccessDialog() {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.check_circle, color: Colors.green[700]),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Commande validée'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
content: Text('Votre commande a été envoyée en cuisine avec succès !'),
|
||||||
|
actions: [
|
||||||
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop(); // Fermer le dialog
|
Navigator.of(context).pop(); // Fermer le dialog
|
||||||
Navigator.of(context).pop(); // Retourner au menu
|
Navigator.of(context).pop(); // Retourner au menu
|
||||||
Navigator.of(context).pop(); // Retourner aux tables
|
Navigator.of(context).pop(); // Retourner aux tables
|
||||||
},
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: Colors.green[700],
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
),
|
||||||
|
child: Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showErrorDialog(String message) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.error, color: Colors.red),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Erreur'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
content: Text(message),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
child: Text('OK'),
|
child: Text('OK'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -369,7 +522,9 @@ class _CartPageState extends State<CartPage> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: _cartItems.isNotEmpty ? _validateOrder : null,
|
onPressed: _cartItems.isNotEmpty && !_isValidating
|
||||||
|
? _showConfirmationDialog
|
||||||
|
: null,
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.green[700],
|
backgroundColor: Colors.green[700],
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
@ -382,6 +537,24 @@ class _CartPageState extends State<CartPage> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
|
if (_isValidating) ...[
|
||||||
|
SizedBox(
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2,
|
||||||
|
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text(
|
||||||
|
'Validation en cours...',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
] else ...[
|
||||||
Icon(Icons.check, size: 20),
|
Icon(Icons.check, size: 20),
|
||||||
SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
Text(
|
Text(
|
||||||
@ -392,6 +565,7 @@ class _CartPageState extends State<CartPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -142,7 +142,19 @@ class _CategoriesPageState extends State<CategoriesPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw Exception('Erreur lors de la suppression (${response.statusCode})');
|
// On essaie de décoder le corps pour extraire un message clair
|
||||||
|
String message;
|
||||||
|
try {
|
||||||
|
final Map<String, dynamic> body = jsonDecode(response.body);
|
||||||
|
message = body['message'] ?? body['error'] ?? response.body;
|
||||||
|
} catch (_) {
|
||||||
|
// Le corps n'est pas en JSON ou est vide
|
||||||
|
message = response.body.isNotEmpty
|
||||||
|
? response.body
|
||||||
|
: 'Statut ${response.statusCode} sans contenu';
|
||||||
|
}
|
||||||
|
|
||||||
|
throw Exception('($message)');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user