Compare commits

..

No commits in common. "12f9fd063ab45c58ddc1e75b331cfc69623ced3f" and "f9b6be710402fa55eef9c021dcbe9538330b9706" have entirely different histories.

7 changed files with 557 additions and 735 deletions

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -177,7 +177,8 @@ class _AccueilPageState extends State<AccueilPage> {
void showTicketPage() { void showTicketPage() {
Get.offAll(TicketPage( Get.offAll(TicketPage(
businessName: 'Youmaz', 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', businessPhoneNumber: '77 446 92 68',
cartItems: selectedProducts, cartItems: selectedProducts,
totalCartPrice: calculateTotalPrice(), totalCartPrice: calculateTotalPrice(),
@ -191,38 +192,37 @@ class _AccueilPageState extends State<AccueilPage> {
appBar: CustomAppBar( appBar: CustomAppBar(
title: "Accueil", title: "Accueil",
subtitle: Text('Bienvenue $username ! (Rôle: $role)', subtitle: Text('Bienvenue $username ! (Rôle: $role)',
style: const TextStyle(color: Colors.white70, fontSize: 14)), style: const TextStyle(color: Colors.white70, fontSize: 14)),
), ),
drawer: CustomDrawer(), drawer: CustomDrawer(),
body: ParticleBackground( body: ParticleBackground(
child: Container( child: Container(
decoration: const BoxDecoration( decoration: const BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [Colors.white, Color.fromARGB(255, 4, 54, 95)]), colors: [Colors.white, Color.fromARGB(255, 4, 54, 95)]),
), ),
child: FutureBuilder<Map<String, List<Product>>>( child: FutureBuilder<Map<String, List<Product>>>(
future: productsFuture, future: productsFuture,
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) { if (snapshot.connectionState == ConnectionState.waiting) {
return const Center( return const Center(
child: CircularProgressIndicator( child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>( valueColor: AlwaysStoppedAnimation<Color>(
Color.fromARGB(255, 4, 54, 95), Color.fromARGB(255, 4, 54, 95),),
), ));
));
} else if (snapshot.hasError) { } else if (snapshot.hasError) {
return const Center( return const Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.error, color: Colors.red, size: 48), Icon(Icons.error, color: Colors.red, size: 48),
SizedBox(height: 16), SizedBox(height: 16),
Text("Erreur de chargement des produits", Text("Erreur de chargement des produits",
style: TextStyle(fontSize: 16, color: Colors.white)), style: TextStyle(fontSize: 16, color: Colors.white)),
], ],
)); ));
} else if (snapshot.hasData) { } else if (snapshot.hasData) {
final productsByCategory = snapshot.data!; final productsByCategory = snapshot.data!;
final categories = productsByCategory.keys.toList(); final categories = productsByCategory.keys.toList();
@ -233,13 +233,15 @@ class _AccueilPageState extends State<AccueilPage> {
Expanded( Expanded(
flex: 3, flex: 3,
child: Container( child: Container(
padding: const EdgeInsets.all(8), padding:const EdgeInsets.all(8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white.withOpacity(0.9), color: Colors.white.withOpacity(0.9),
borderRadius: const BorderRadius.only( borderRadius: const BorderRadius.only(
topRight: Radius.circular(20), topRight: Radius.circular(20),
),
), ),
),
child: ListView.builder( child: ListView.builder(
itemCount: categories.length, itemCount: categories.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
@ -250,9 +252,8 @@ class _AccueilPageState extends State<AccueilPage> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Container( Container(
margin: margin: const EdgeInsets.symmetric(vertical: 8),
const EdgeInsets.symmetric(vertical: 8), padding:const EdgeInsets.all(12),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Color.fromARGB(255, 4, 54, 95), color: Color.fromARGB(255, 4, 54, 95),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
@ -260,8 +261,7 @@ class _AccueilPageState extends State<AccueilPage> {
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.1), color: Colors.black.withOpacity(0.1),
blurRadius: 4, blurRadius: 4,
offset: Offset(0, 2), offset: Offset(0, 2),)
)
], ],
), ),
child: Center( child: Center(
@ -300,16 +300,17 @@ class _AccueilPageState extends State<AccueilPage> {
); );
}, },
), ),
),
// Section panier
), ),
Expanded(
flex: 1, // Section panier
),
Expanded(flex: 1,
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey[200], color: Colors.grey[200],
borderRadius: const BorderRadius.only( borderRadius:const BorderRadius.only(
topLeft: Radius.circular(20), topLeft: Radius.circular(20),
), ),
boxShadow: [ boxShadow: [
@ -330,7 +331,7 @@ class _AccueilPageState extends State<AccueilPage> {
color: Color.fromARGB(255, 4, 54, 95), color: Color.fromARGB(255, 4, 54, 95),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
child: const Text( child:const Text(
'Panier', 'Panier',
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: 20,
@ -341,23 +342,22 @@ class _AccueilPageState extends State<AccueilPage> {
), ),
), ),
SizedBox(height: 16), SizedBox(height: 16),
// Liste des produits dans le panier // Liste des produits dans le panier
Expanded( Expanded(
child: selectedProducts.isEmpty child: selectedProducts.isEmpty
? const Center( ? const Center(
child: Column( child: Column(
mainAxisAlignment: mainAxisAlignment: MainAxisAlignment.center,
MainAxisAlignment.center,
children: [ children: [
Icon(Icons.shopping_cart, Icon(Icons.shopping_cart,
size: 48, color: Colors.grey), size: 48, color: Colors.grey),
SizedBox(height: 16), SizedBox(height: 16),
Text( Text(
"Votre panier est vide", "Votre panier est vide",
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: Colors.grey), color: Colors.grey),
), ),
], ],
), ),
@ -365,49 +365,39 @@ class _AccueilPageState extends State<AccueilPage> {
: ListView.builder( : ListView.builder(
itemCount: selectedProducts.length, itemCount: selectedProducts.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final cartItem = final cartItem = selectedProducts[index];
selectedProducts[index];
return Card( return Card(
margin: margin: EdgeInsets.symmetric(vertical: 4),
EdgeInsets.symmetric(vertical: 4),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: borderRadius: BorderRadius.circular(10),
BorderRadius.circular(10),
), ),
elevation: 2, elevation: 2,
child: ListTile( child: ListTile(
contentPadding: contentPadding: EdgeInsets.symmetric(
EdgeInsets.symmetric( horizontal: 12, vertical: 4),
horizontal: 12, leading: Icon(Icons.shopping_basket,
vertical: 4), color: Color.fromARGB(255, 4, 54, 95),),
leading: Icon(
Icons.shopping_basket,
color: Color.fromARGB(
255, 4, 54, 95),
),
title: Text( title: Text(
cartItem.product.name, cartItem.product.name,
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
), ),
subtitle: Text( subtitle: Text(
'${NumberFormat('#,##0').format(cartItem.product.price)} MGA x ${cartItem.quantity}', '${NumberFormat('#,##0').format(cartItem.product.price)} FCFA x ${cartItem.quantity}',
style: style:const TextStyle(fontSize: 14),
const TextStyle(fontSize: 14),
), ),
trailing: Row( trailing: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text( Text(
'${NumberFormat('#,##0').format(cartItem.product.price * cartItem.quantity)}', '${NumberFormat('#,##0').format(cartItem.product.price * cartItem.quantity)}',
style: const TextStyle( style:const TextStyle(
fontWeight: fontWeight: FontWeight.bold),
FontWeight.bold),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
IconButton( IconButton(
icon: const Icon(Icons.delete, icon: const Icon(Icons.delete,
color: Colors.red), color: Colors.red),
onPressed: () { onPressed: () {
setState(() { setState(() {
selectedProducts selectedProducts
@ -422,7 +412,7 @@ class _AccueilPageState extends State<AccueilPage> {
}, },
), ),
), ),
// Total et paiement // Total et paiement
Container( Container(
padding: EdgeInsets.all(12), padding: EdgeInsets.all(12),
@ -440,20 +430,18 @@ class _AccueilPageState extends State<AccueilPage> {
child: Column( child: Column(
children: [ children: [
Row( Row(
mainAxisAlignment: mainAxisAlignment: MainAxisAlignment.spaceBetween,
MainAxisAlignment.spaceBetween,
children: [ children: [
const Text('Total:', const Text('Total:',
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold)), fontWeight: FontWeight.bold)),
Text( Text(
'${NumberFormat('#,##0.00').format(calculateTotalPrice())} FCFA', '${NumberFormat('#,##0.00').format(calculateTotalPrice())} FCFA',
style: TextStyle( style: TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 4, 54, 95), color: Color.fromARGB(255, 4, 54, 95),),
),
), ),
], ],
), ),
@ -472,8 +460,7 @@ class _AccueilPageState extends State<AccueilPage> {
), ),
onChanged: (value) { onChanged: (value) {
setState(() { setState(() {
amountPaid = amountPaid = double.tryParse(value) ?? 0;
double.tryParse(value) ?? 0;
}); });
}, },
), ),
@ -481,15 +468,14 @@ class _AccueilPageState extends State<AccueilPage> {
ElevatedButton.icon( ElevatedButton.icon(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.green, backgroundColor: Colors.green,
padding: padding: EdgeInsets.symmetric(vertical: 16),
EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
), ),
onPressed: saveOrderToDatabase, onPressed: saveOrderToDatabase,
icon: const Icon(Icons.check_circle), icon:const Icon(Icons.check_circle),
label: const Text( label:const Text(
'Valider la commande', 'Valider la commande',
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
@ -502,14 +488,13 @@ class _AccueilPageState extends State<AccueilPage> {
), ),
], ],
), ),
), ),)
)
], ],
); );
} else { } else {
return const Center( return const Center(
child: Text("Aucun produit disponible", child: Text("Aucun produit disponible",
style: TextStyle(color: Colors.white)), style: TextStyle(color: Colors.white)),
); );
} }
}, },
@ -524,4 +509,4 @@ class _AccueilPageState extends State<AccueilPage> {
_amountController.dispose(); _amountController.dispose();
super.dispose(); super.dispose();
} }
} }

View File

@ -8,21 +8,20 @@ import 'package:logging/logging.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
try { try {
// Initialiser les bases de données une seule fois // Initialiser les bases de données une seule fois
// await AppDatabase.instance.deleteDatabaseFile(); // await AppDatabase.instance.deleteDatabaseFile();
// await ProductDatabase.instance.deleteDatabaseFile(); //await ProductDatabase.instance.deleteDatabaseFile();
await ProductDatabase.instance.initDatabase(); await ProductDatabase.instance.initDatabase();
await AppDatabase.instance.initDatabase(); await AppDatabase.instance.initDatabase();
// Afficher les informations de la base (pour debug) // Afficher les informations de la base (pour debug)
await AppDatabase.instance.printDatabaseInfo(); await AppDatabase.instance.printDatabaseInfo();
Get.put( Get.put(UserController()); // Ajoute ce code AVANT tout accès au UserController
UserController()); // Ajoute ce code AVANT tout accès au UserController
setupLogger(); setupLogger();
runApp(const GetMaterialApp( runApp(const GetMaterialApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
home: MyApp(), home: MyApp(),
@ -45,4 +44,4 @@ void setupLogger() {
Logger.root.onRecord.listen((record) { Logger.root.onRecord.listen((record) {
print('${record.level.name}: ${record.time}: ${record.message}'); print('${record.level.name}: ${record.time}: ${record.message}');
}); });
} }