Browse Source

FCFA to MGA

31052025_01
Stephane 6 months ago
parent
commit
c71f663346
  1. 4
      lib/Components/panier.dart
  2. 183
      lib/Views/HandleProduct.dart
  3. 2
      lib/Views/bilanMois.dart
  4. 4
      lib/Views/listCommandeHistory.dart
  5. 30
      lib/Views/ticketPage.dart
  6. 81
      lib/accueil.dart
  7. 5
      lib/main.dart

4
lib/Components/panier.dart

@ -53,7 +53,7 @@ class PanierPage extends StatelessWidget {
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text('${product.price.toStringAsFixed(2)} fcfa'),
Text('${product.price.toStringAsFixed(2)} MGA'),
const SizedBox(width: 8),
Text('x $quantity'),
const SizedBox(width: 8),
@ -78,7 +78,7 @@ class PanierPage extends StatelessWidget {
),
const SizedBox(height: 16),
Text(
'Total: ${calculateTotalPrice().toStringAsFixed(2)} fcfa',
'Total: ${calculateTotalPrice().toStringAsFixed(2)} MGA',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,

183
lib/Views/HandleProduct.dart

@ -13,7 +13,6 @@ import '../Components/app_bar.dart';
import '../Models/produit.dart';
import '../Services/productDatabase.dart';
class ProductManagementPage extends StatefulWidget {
const ProductManagementPage({super.key});
@ -32,7 +31,13 @@ class _ProductManagementPageState extends State<ProductManagementPage> {
// Catégories prédéfinies pour l'ajout de produits
final List<String> _predefinedCategories = [
'Sucré', 'Salé', 'Jus', 'Gateaux', 'Snacks', 'Boissons', 'Non catégorisé'
'Sucré',
'Salé',
'Jus',
'Gateaux',
'Snacks',
'Boissons',
'Non catégorisé'
];
@override
@ -48,28 +53,22 @@ class _ProductManagementPageState extends State<ProductManagementPage> {
super.dispose();
}
//======================================================================================================
// Ajoutez ces variables à la classe _ProductManagementPageState
bool _isImporting = false;
double _importProgress = 0.0;
String _importStatusText = '';
bool _isImporting = false;
double _importProgress = 0.0;
String _importStatusText = '';
// Ajoutez ces méthodes à la classe _ProductManagementPageState
void _resetImportState() {
void _resetImportState() {
setState(() {
_isImporting = false;
_importProgress = 0.0;
_importStatusText = '';
});
}
}
void _showExcelCompatibilityError() {
void _showExcelCompatibilityError() {
Get.dialog(
AlertDialog(
title: const Text('Fichier Excel incompatible'),
@ -78,8 +77,7 @@ void _showExcelCompatibilityError() {
'Solutions recommandées :\n'
'• Téléchargez notre modèle Excel et copiez-y vos données\n'
'• Ou exportez votre fichier en format simple: Classeur Excel .xlsx depuis Excel\n'
'• Ou créez un nouveau fichier Excel simple sans formatage complexe'
),
'• Ou créez un nouveau fichier Excel simple sans formatage complexe'),
actions: [
TextButton(
onPressed: () => Get.back(),
@ -99,9 +97,9 @@ void _showExcelCompatibilityError() {
],
),
);
}
}
Future<void> _downloadExcelTemplate() async {
Future<void> _downloadExcelTemplate() async {
try {
final excel = Excel.createExcel();
excel.delete('Sheet1');
@ -112,7 +110,8 @@ Future<void> _downloadExcelTemplate() async {
final headers = ['Nom', 'Prix', 'Catégorie', 'Description', 'Stock'];
for (int i = 0; i < headers.length; i++) {
final cell = sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: 0));
final cell =
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: 0));
cell.value = headers[i];
cell.cellStyle = CellStyle(
bold: true,
@ -124,12 +123,19 @@ Future<void> _downloadExcelTemplate() async {
['Croissant', '1.50', 'Sucré', 'Délicieux croissant beurré', '20'],
['Sandwich jambon', '4.00', 'Salé', 'Sandwich fait maison', '15'],
['Jus d\'orange', '2.50', 'Jus', 'Jus d\'orange frais', '30'],
['Gâteau chocolat', '18.00', 'Gateaux', 'Gâteau au chocolat portion 8 personnes', '5'],
[
'Gâteau chocolat',
'18.00',
'Gateaux',
'Gâteau au chocolat portion 8 personnes',
'5'
],
];
for (int row = 0; row < examples.length; row++) {
for (int col = 0; col < examples[row].length; col++) {
final cell = sheet.cell(CellIndex.indexByColumnRow(columnIndex: col, rowIndex: row + 1));
final cell = sheet.cell(
CellIndex.indexByColumnRow(columnIndex: col, rowIndex: row + 1));
cell.value = examples[row][col];
}
}
@ -171,13 +177,13 @@ Future<void> _downloadExcelTemplate() async {
Get.snackbar('Erreur', 'Erreur lors de la création du modèle: $e');
debugPrint('Erreur création modèle Excel: $e');
}
}
}
Future<void> _importFromExcel() async {
Future<void> _importFromExcel() async {
try {
final result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['xlsx', 'xls','csv'],
allowedExtensions: ['xlsx', 'xls', 'csv'],
allowMultiple: false,
);
@ -232,11 +238,13 @@ Future<void> _importFromExcel() async {
_resetImportState();
debugPrint('Erreur décodage Excel: $e');
if (e.toString().contains('styles') || e.toString().contains('Damaged')) {
if (e.toString().contains('styles') ||
e.toString().contains('Damaged')) {
_showExcelCompatibilityError();
return;
} else {
Get.snackbar('Erreur', 'Impossible de lire le fichier Excel. Format non supporté.');
Get.snackbar('Erreur',
'Impossible de lire le fichier Excel. Format non supporté.');
return;
}
}
@ -341,10 +349,12 @@ Future<void> _importFromExcel() async {
}
String reference = _generateUniqueReference();
var existingProduct = await _productDatabase.getProductByReference(reference);
var existingProduct =
await _productDatabase.getProductByReference(reference);
while (existingProduct != null) {
reference = _generateUniqueReference();
existingProduct = await _productDatabase.getProductByReference(reference);
existingProduct =
await _productDatabase.getProductByReference(reference);
}
final product = Product(
@ -367,7 +377,6 @@ Future<void> _importFromExcel() async {
await _productDatabase.createProduct(product);
successCount++;
} catch (e) {
errorCount++;
errorMessages.add('Ligne ${i + 1}: Erreur de traitement - $e');
@ -403,16 +412,15 @@ Future<void> _importFromExcel() async {
// Recharger la liste des produits après importation
_loadProducts();
} catch (e) {
_resetImportState();
Get.snackbar('Erreur', 'Erreur lors de l\'importation Excel: $e');
debugPrint('Erreur générale import Excel: $e');
}
}
}
// Ajoutez ce widget dans votre méthode build, par exemple dans la partie supérieure
Widget _buildImportProgressIndicator() {
Widget _buildImportProgressIndicator() {
if (!_isImporting) return const SizedBox.shrink();
return Container(
@ -459,7 +467,8 @@ Widget _buildImportProgressIndicator() {
],
),
);
}
}
//=============================================================================================================================
Future<void> _loadProducts() async {
setState(() => _isLoading = true);
@ -531,7 +540,8 @@ Widget _buildImportProgressIndicator() {
final path = '${directory.path}/$reference.png';
try {
final picData = await painter.toImageData(2048, format: ImageByteFormat.png);
final picData =
await painter.toImageData(2048, format: ImageByteFormat.png);
if (picData != null) {
await File(path).writeAsBytes(picData.buffer.asUint8List());
} else {
@ -551,7 +561,8 @@ Widget _buildImportProgressIndicator() {
final descriptionController = TextEditingController();
final imageController = TextEditingController();
String selectedCategory = _predefinedCategories.last; // 'Non catégorisé' par défaut
String selectedCategory =
_predefinedCategories.last; // 'Non catégorisé' par défaut
File? pickedImage;
String? qrPreviewData;
String? currentReference;
@ -579,7 +590,8 @@ Widget _buildImportProgressIndicator() {
color: Colors.green.shade100,
borderRadius: BorderRadius.circular(8),
),
child: Icon(Icons.add_shopping_cart, color: Colors.green.shade700),
child:
Icon(Icons.add_shopping_cart, color: Colors.green.shade700),
),
const SizedBox(width: 12),
const Text('Ajouter un produit'),
@ -605,11 +617,13 @@ Widget _buildImportProgressIndicator() {
),
child: Row(
children: [
Icon(Icons.info, color: Colors.red.shade600, size: 16),
Icon(Icons.info,
color: Colors.red.shade600, size: 16),
const SizedBox(width: 8),
const Text(
'Les champs marqués d\'un * sont obligatoires',
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
style: TextStyle(
fontSize: 12, fontWeight: FontWeight.w500),
),
],
),
@ -640,9 +654,10 @@ Widget _buildImportProgressIndicator() {
Expanded(
child: TextField(
controller: priceController,
keyboardType: const TextInputType.numberWithOptions(decimal: true),
keyboardType: const TextInputType.numberWithOptions(
decimal: true),
decoration: InputDecoration(
labelText: 'Prix (FCFA) *',
labelText: 'Prix (MGA) *',
border: const OutlineInputBorder(),
prefixIcon: const Icon(Icons.attach_money),
filled: true,
@ -671,8 +686,10 @@ Widget _buildImportProgressIndicator() {
// Catégorie
DropdownButtonFormField<String>(
value: selectedCategory,
items: _predefinedCategories.map((category) =>
DropdownMenuItem(value: category, child: Text(category))).toList(),
items: _predefinedCategories
.map((category) => DropdownMenuItem(
value: category, child: Text(category)))
.toList(),
onChanged: (value) {
setDialogState(() => selectedCategory = value!);
},
@ -741,10 +758,13 @@ Widget _buildImportProgressIndicator() {
const SizedBox(width: 8),
ElevatedButton.icon(
onPressed: () async {
final result = await FilePicker.platform.pickFiles(type: FileType.image);
if (result != null && result.files.single.path != null) {
final result = await FilePicker.platform
.pickFiles(type: FileType.image);
if (result != null &&
result.files.single.path != null) {
setDialogState(() {
pickedImage = File(result.files.single.path!);
pickedImage =
File(result.files.single.path!);
imageController.text = pickedImage!.path;
});
}
@ -767,11 +787,13 @@ Widget _buildImportProgressIndicator() {
width: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.grey.shade300),
border:
Border.all(color: Colors.grey.shade300),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.file(pickedImage!, fit: BoxFit.cover),
child: Image.file(pickedImage!,
fit: BoxFit.cover),
),
),
),
@ -793,7 +815,8 @@ Widget _buildImportProgressIndicator() {
children: [
Row(
children: [
Icon(Icons.qr_code_2, color: Colors.green.shade700),
Icon(Icons.qr_code_2,
color: Colors.green.shade700),
const SizedBox(width: 8),
Text(
'Aperçu du QR Code',
@ -823,7 +846,8 @@ Widget _buildImportProgressIndicator() {
const SizedBox(height: 8),
Text(
'Réf: $currentReference',
style: const TextStyle(fontSize: 10, color: Colors.grey),
style: const TextStyle(
fontSize: 10, color: Colors.grey),
),
],
),
@ -852,12 +876,15 @@ Widget _buildImportProgressIndicator() {
try {
// Générer une référence unique et vérifier son unicité
String finalReference = currentReference ?? _generateUniqueReference();
var existingProduct = await _productDatabase.getProductByReference(finalReference);
String finalReference =
currentReference ?? _generateUniqueReference();
var existingProduct = await _productDatabase
.getProductByReference(finalReference);
while (existingProduct != null) {
finalReference = _generateUniqueReference();
existingProduct = await _productDatabase.getProductByReference(finalReference);
existingProduct = await _productDatabase
.getProductByReference(finalReference);
}
// Générer le QR code
@ -988,9 +1015,12 @@ Widget _buildImportProgressIndicator() {
void _editProduct(Product product) {
final nameController = TextEditingController(text: product.name);
final priceController = TextEditingController(text: product.price.toString());
final stockController = TextEditingController(text: product.stock.toString());
final descriptionController = TextEditingController(text: product.description ?? '');
final priceController =
TextEditingController(text: product.price.toString());
final stockController =
TextEditingController(text: product.stock.toString());
final descriptionController =
TextEditingController(text: product.description ?? '');
final imageController = TextEditingController(text: product.image);
String selectedCategory = product.category;
@ -1013,17 +1043,16 @@ Widget _buildImportProgressIndicator() {
),
),
const SizedBox(height: 16),
TextField(
controller: priceController,
keyboardType: const TextInputType.numberWithOptions(decimal: true),
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
decoration: const InputDecoration(
labelText: 'Prix*',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
TextField(
controller: stockController,
keyboardType: TextInputType.number,
@ -1033,7 +1062,6 @@ Widget _buildImportProgressIndicator() {
),
),
const SizedBox(height: 16),
StatefulBuilder(
builder: (context, setDialogState) {
return Column(
@ -1053,11 +1081,14 @@ Widget _buildImportProgressIndicator() {
const SizedBox(width: 8),
ElevatedButton(
onPressed: () async {
final result = await FilePicker.platform.pickFiles(type: FileType.image);
if (result != null && result.files.single.path != null) {
final result = await FilePicker.platform
.pickFiles(type: FileType.image);
if (result != null &&
result.files.single.path != null) {
if (context.mounted) {
setDialogState(() {
pickedImage = File(result.files.single.path!);
pickedImage =
File(result.files.single.path!);
imageController.text = pickedImage!.path;
});
}
@ -1068,7 +1099,6 @@ Widget _buildImportProgressIndicator() {
],
),
const SizedBox(height: 16),
if (pickedImage != null || product.image!.isNotEmpty)
Container(
height: 100,
@ -1082,16 +1112,19 @@ Widget _buildImportProgressIndicator() {
child: pickedImage != null
? Image.file(pickedImage!, fit: BoxFit.cover)
: (product.image!.isNotEmpty
? Image.file(File(product.image!), fit: BoxFit.cover)
? Image.file(File(product.image!),
fit: BoxFit.cover)
: const Icon(Icons.image, size: 50)),
),
),
const SizedBox(height: 16),
DropdownButtonFormField<String>(
value: selectedCategory,
items: _categories.skip(1).map((category) =>
DropdownMenuItem(value: category, child: Text(category))).toList(),
items: _categories
.skip(1)
.map((category) => DropdownMenuItem(
value: category, child: Text(category)))
.toList(),
onChanged: (value) {
if (context.mounted) {
setDialogState(() => selectedCategory = value!);
@ -1103,7 +1136,6 @@ Widget _buildImportProgressIndicator() {
),
),
const SizedBox(height: 16),
TextField(
controller: descriptionController,
maxLines: 3,
@ -1197,7 +1229,8 @@ Widget _buildImportProgressIndicator() {
Get.snackbar('Erreur', 'Suppression échouée: $e');
}
},
child: const Text('Supprimer', style: TextStyle(color: Colors.white)),
child:
const Text('Supprimer', style: TextStyle(color: Colors.white)),
),
],
),
@ -1259,7 +1292,8 @@ Widget _buildImportProgressIndicator() {
Row(
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
padding: const EdgeInsets.symmetric(
horizontal: 8, vertical: 2),
decoration: BoxDecoration(
color: Colors.blue.shade100,
borderRadius: BorderRadius.circular(12),
@ -1408,8 +1442,10 @@ Widget _buildImportProgressIndicator() {
),
child: DropdownButton<String>(
value: _selectedCategory,
items: _categories.map((category) =>
DropdownMenuItem(value: category, child: Text(category))).toList(),
items: _categories
.map((category) => DropdownMenuItem(
value: category, child: Text(category)))
.toList(),
onChanged: (value) {
setState(() {
_selectedCategory = value!;
@ -1439,7 +1475,8 @@ Widget _buildImportProgressIndicator() {
color: Colors.grey,
),
),
if (_searchController.text.isNotEmpty || _selectedCategory != 'Tous')
if (_searchController.text.isNotEmpty ||
_selectedCategory != 'Tous')
TextButton.icon(
onPressed: () {
setState(() {

2
lib/Views/bilanMois.dart

@ -38,7 +38,7 @@ class _BilanMoisState extends State<BilanMois> {
children: [
_buildInfoCard(
title: 'Chiffre réalisé',
value: '${controller.totalSum.value.toStringAsFixed(2)} fcfa',
value: '${controller.totalSum.value.toStringAsFixed(2)} MGA',
color: Colors.green,
icon: Icons.monetization_on,
),

4
lib/Views/listCommandeHistory.dart

@ -112,7 +112,7 @@ class HistoryDetailPage extends StatelessWidget {
),
),
Text(
'Total Somme: $totalSum fcfa',
'Total Somme: $totalSum MGA',
style: const TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
@ -197,7 +197,7 @@ class HistoryDetailPage extends StatelessWidget {
),
],
),
subtitle: Text('Total: ${order.totalPrice} fcfa'),
subtitle: Text('Total: ${order.totalPrice} MGA'),
trailing: Text('Date: ${order.dateTime}'),
leading: Text('vendeur: ${order.user}'),
onTap: () {

30
lib/Views/ticketPage.dart

@ -86,11 +86,11 @@ class TicketPage extends StatelessWidget {
width: 1,
),
PosColumn(
text: '${product.price.toStringAsFixed(2)} fcfa',
text: '${product.price.toStringAsFixed(2)} MGA',
width: 1,
),
PosColumn(
text: '${productTotal.toStringAsFixed(2)} fcfa',
text: '${productTotal.toStringAsFixed(2)} MGA',
width: 1,
),
]);
@ -104,7 +104,7 @@ class TicketPage extends StatelessWidget {
styles: const PosStyles(align: PosAlign.left, bold: true),
),
PosColumn(
text: '${totalCartPrice.toStringAsFixed(2)} fcfa',
text: '${totalCartPrice.toStringAsFixed(2)} MGA',
width: 1,
styles: const PosStyles(align: PosAlign.left, bold: true),
),
@ -116,7 +116,7 @@ class TicketPage extends StatelessWidget {
styles: const PosStyles(align: PosAlign.left),
),
PosColumn(
text: '${amountPaid.toStringAsFixed(2)} fcfa',
text: '${amountPaid.toStringAsFixed(2)} MGA',
width: 1,
styles: const PosStyles(align: PosAlign.left),
),
@ -128,7 +128,7 @@ class TicketPage extends StatelessWidget {
styles: const PosStyles(align: PosAlign.left),
),
PosColumn(
text: '${(amountPaid - totalCartPrice).toStringAsFixed(2)} fcfa',
text: '${(amountPaid - totalCartPrice).toStringAsFixed(2)} MGA',
width: 1,
styles: const PosStyles(align: PosAlign.left),
),
@ -179,8 +179,8 @@ class TicketPage extends StatelessWidget {
return [
product.name,
quantity.toString(),
'${product.price.toStringAsFixed(2)} fcfa',
'${productTotal.toStringAsFixed(2)} fcfa',
'${product.price.toStringAsFixed(2)} MGA',
'${productTotal.toStringAsFixed(2)} MGA',
];
}).toList(),
],
@ -194,7 +194,7 @@ class TicketPage extends StatelessWidget {
pw.Text('Total :',
style: pw.TextStyle(
fontSize: 18, fontWeight: pw.FontWeight.bold)),
pw.Text('${totalCartPrice.toStringAsFixed(2)} fcfa',
pw.Text('${totalCartPrice.toStringAsFixed(2)} MGA',
style: pw.TextStyle(
fontSize: 18, fontWeight: pw.FontWeight.bold)),
],
@ -207,7 +207,7 @@ class TicketPage extends StatelessWidget {
children: [
pw.Text('Somme remise :',
style: const pw.TextStyle(fontSize: 16)),
pw.Text('${amountPaid.toStringAsFixed(2)} fcfa',
pw.Text('${amountPaid.toStringAsFixed(2)} MGA',
style: const pw.TextStyle(fontSize: 16)),
],
),
@ -218,7 +218,7 @@ class TicketPage extends StatelessWidget {
pw.Text('Somme rendue :',
style: const pw.TextStyle(fontSize: 16)),
pw.Text(
'${(amountPaid - totalCartPrice).toStringAsFixed(2)} fcfa',
'${(amountPaid - totalCartPrice).toStringAsFixed(2)} MGA',
style: const pw.TextStyle(fontSize: 16)),
],
),
@ -387,14 +387,14 @@ class TicketPage extends StatelessWidget {
TableCell(
child: Center(
child: Text(
'${product.price.toStringAsFixed(2)} fcfa',
'${product.price.toStringAsFixed(2)} MGA',
),
),
),
TableCell(
child: Center(
child: Text(
'${productTotal.toStringAsFixed(2)} fcfa',
'${productTotal.toStringAsFixed(2)} MGA',
),
),
),
@ -421,7 +421,7 @@ class TicketPage extends StatelessWidget {
),
),
Text(
'${totalOrderAmount.toStringAsFixed(2)} fcfa',
'${totalOrderAmount.toStringAsFixed(2)} MGA',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
@ -446,7 +446,7 @@ class TicketPage extends StatelessWidget {
),
),
Text(
'${amountPaid.toStringAsFixed(2)} fcfa',
'${amountPaid.toStringAsFixed(2)} MGA',
style: const TextStyle(
fontSize: 16,
),
@ -464,7 +464,7 @@ class TicketPage extends StatelessWidget {
),
),
Text(
'${change.toStringAsFixed(2)} fcfa',
'${change.toStringAsFixed(2)} MGA',
style: const TextStyle(
fontSize: 16,
),

81
lib/accueil.dart

@ -177,8 +177,7 @@ class _AccueilPageState extends State<AccueilPage> {
void showTicketPage() {
Get.offAll(TicketPage(
businessName: 'Youmaz',
businessAddress:
'quartier escale, Diourbel, Sénégal, en face de Sonatel',
businessAddress: 'quartier escale, Diourbel, Sénégal, en face de Sonatel',
businessPhoneNumber: '77 446 92 68',
cartItems: selectedProducts,
totalCartPrice: calculateTotalPrice(),
@ -210,7 +209,8 @@ class _AccueilPageState extends State<AccueilPage> {
return const Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
Color.fromARGB(255, 4, 54, 95),),
Color.fromARGB(255, 4, 54, 95),
),
));
} else if (snapshot.hasError) {
return const Center(
@ -233,14 +233,12 @@ class _AccueilPageState extends State<AccueilPage> {
Expanded(
flex: 3,
child: Container(
padding:const EdgeInsets.all(8),
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.9),
borderRadius: const BorderRadius.only(
topRight: Radius.circular(20),
),
),
child: ListView.builder(
itemCount: categories.length,
@ -252,8 +250,9 @@ class _AccueilPageState extends State<AccueilPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.symmetric(vertical: 8),
padding:const EdgeInsets.all(12),
margin:
const EdgeInsets.symmetric(vertical: 8),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Color.fromARGB(255, 4, 54, 95),
borderRadius: BorderRadius.circular(12),
@ -261,7 +260,8 @@ class _AccueilPageState extends State<AccueilPage> {
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 4,
offset: Offset(0, 2),)
offset: Offset(0, 2),
)
],
),
child: Center(
@ -303,14 +303,13 @@ class _AccueilPageState extends State<AccueilPage> {
),
// Section panier
),
Expanded(flex: 1,
Expanded(
flex: 1,
child: Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius:const BorderRadius.only(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(20),
),
boxShadow: [
@ -331,7 +330,7 @@ class _AccueilPageState extends State<AccueilPage> {
color: Color.fromARGB(255, 4, 54, 95),
borderRadius: BorderRadius.circular(12),
),
child:const Text(
child: const Text(
'Panier',
style: TextStyle(
fontSize: 20,
@ -348,7 +347,8 @@ class _AccueilPageState extends State<AccueilPage> {
child: selectedProducts.isEmpty
? const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Icon(Icons.shopping_cart,
size: 48, color: Colors.grey),
@ -365,34 +365,44 @@ class _AccueilPageState extends State<AccueilPage> {
: ListView.builder(
itemCount: selectedProducts.length,
itemBuilder: (context, index) {
final cartItem = selectedProducts[index];
final cartItem =
selectedProducts[index];
return Card(
margin: EdgeInsets.symmetric(vertical: 4),
margin:
EdgeInsets.symmetric(vertical: 4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
borderRadius:
BorderRadius.circular(10),
),
elevation: 2,
child: ListTile(
contentPadding: EdgeInsets.symmetric(
horizontal: 12, vertical: 4),
leading: Icon(Icons.shopping_basket,
color: Color.fromARGB(255, 4, 54, 95),),
contentPadding:
EdgeInsets.symmetric(
horizontal: 12,
vertical: 4),
leading: Icon(
Icons.shopping_basket,
color: Color.fromARGB(
255, 4, 54, 95),
),
title: Text(
cartItem.product.name,
style: const TextStyle(
fontWeight: FontWeight.bold),
),
subtitle: Text(
'${NumberFormat('#,##0').format(cartItem.product.price)} FCFA x ${cartItem.quantity}',
style:const TextStyle(fontSize: 14),
'${NumberFormat('#,##0').format(cartItem.product.price)} MGA x ${cartItem.quantity}',
style:
const TextStyle(fontSize: 14),
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'${NumberFormat('#,##0').format(cartItem.product.price * cartItem.quantity)}',
style:const TextStyle(
fontWeight: FontWeight.bold),
style: const TextStyle(
fontWeight:
FontWeight.bold),
),
const SizedBox(width: 8),
IconButton(
@ -430,7 +440,8 @@ class _AccueilPageState extends State<AccueilPage> {
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
const Text('Total:',
style: TextStyle(
@ -441,7 +452,8 @@ class _AccueilPageState extends State<AccueilPage> {
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 4, 54, 95),),
color: Color.fromARGB(255, 4, 54, 95),
),
),
],
),
@ -460,7 +472,8 @@ class _AccueilPageState extends State<AccueilPage> {
),
onChanged: (value) {
setState(() {
amountPaid = double.tryParse(value) ?? 0;
amountPaid =
double.tryParse(value) ?? 0;
});
},
),
@ -468,14 +481,15 @@ class _AccueilPageState extends State<AccueilPage> {
ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green,
padding: EdgeInsets.symmetric(vertical: 16),
padding:
EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
onPressed: saveOrderToDatabase,
icon:const Icon(Icons.check_circle),
label:const Text(
icon: const Icon(Icons.check_circle),
label: const Text(
'Valider la commande',
style: TextStyle(
fontSize: 16,
@ -488,7 +502,8 @@ class _AccueilPageState extends State<AccueilPage> {
),
],
),
),)
),
)
],
);
} else {

5
lib/main.dart

@ -12,14 +12,15 @@ void main() async {
try {
// Initialiser les bases de données une seule fois
// await AppDatabase.instance.deleteDatabaseFile();
//await ProductDatabase.instance.deleteDatabaseFile();
// await ProductDatabase.instance.deleteDatabaseFile();
await ProductDatabase.instance.initDatabase();
await AppDatabase.instance.initDatabase();
// Afficher les informations de la base (pour debug)
await AppDatabase.instance.printDatabaseInfo();
Get.put(UserController()); // Ajoute ce code AVANT tout accès au UserController
Get.put(
UserController()); // Ajoute ce code AVANT tout accès au UserController
setupLogger();
runApp(const GetMaterialApp(

Loading…
Cancel
Save