Browse Source

commit

master
andrymodeste 4 months ago
parent
commit
45688ec98a
  1. 7
      lib/models/payment_method.dart
  2. 8
      lib/pages/facture_screen.dart
  3. 442
      lib/services/pdf_service.dart
  4. 82
      lib/widgets/bottom_navigation.dart

7
lib/models/payment_method.dart

@ -24,6 +24,13 @@ final List<PaymentMethod> paymentMethods = [
icon: Icons.phone, icon: Icons.phone,
color: Color(0xFF4285F4), color: Color(0xFF4285F4),
), ),
const PaymentMethod(
id: 'orange_money',
name: 'Orange Money',
description: 'Paiement mobile Orange Money',
icon: Icons.phone,
color: Color(0xFF4285F4),
),
const PaymentMethod( const PaymentMethod(
id: 'carte', id: 'carte',
name: 'Carte Bancaire', name: 'Carte Bancaire',

8
lib/pages/facture_screen.dart

@ -135,6 +135,14 @@ class _FactureScreenState extends State<FactureScreen> {
'Contact: +261 34 12 34 56', 'Contact: +261 34 12 34 56',
style: TextStyle(fontSize: 12, color: Colors.black87), style: TextStyle(fontSize: 12, color: Colors.black87),
), ),
Text(
'NIF: 4002141594',
style: TextStyle(fontSize: 12, color: Colors.black87),
),
Text(
'STAT: 10715 33 2025 0 00414',
style: TextStyle(fontSize: 12, color: Colors.black87),
),
], ],
); );
} }

442
lib/services/pdf_service.dart

@ -60,6 +60,8 @@ class PlatformPrintService {
'ville': 'Madagascar', 'ville': 'Madagascar',
'contact': '261348415301', 'contact': '261348415301',
'email': 'contact@careeragency.mg', 'email': 'contact@careeragency.mg',
'nif': '4002141594',
'stat': '10715 33 2025 0 00414',
}; };
final factureNumber = final factureNumber =
@ -69,223 +71,267 @@ class PlatformPrintService {
pdf.addPage( pdf.addPage(
pw.Page( pw.Page(
pageFormat: ticket58mmFormat, pageFormat: ticket58mmFormat,
margin: const pw.EdgeInsets.all(2), // 🔧 Marges minimales
build: (pw.Context context) { build: (pw.Context context) {
return pw.Column( return pw.Container(
crossAxisAlignment: pw.CrossAxisAlignment.center, width: double.infinity, // 🔧 Forcer la largeur complète
children: [ child: pw.Column(
// En-tête Restaurant (centré et compact) crossAxisAlignment:
pw.Text( pw.CrossAxisAlignment.start, // 🔧 Alignement à gauche
restaurantInfo['nom']!, children: [
style: pw.TextStyle( // En-tête Restaurant (centré et compact)
fontSize: titleSize, pw.Container(
fontWeight: pw.FontWeight.bold, width: double.infinity,
), child: pw.Text(
textAlign: pw.TextAlign.center, restaurantInfo['nom']!,
),
pw.SizedBox(height: 1),
pw.Text(
restaurantInfo['adresse']!,
style: pw.TextStyle(fontSize: smallSize),
textAlign: pw.TextAlign.center,
),
pw.Text(
restaurantInfo['ville']!,
style: pw.TextStyle(fontSize: smallSize),
textAlign: pw.TextAlign.center,
),
pw.Text(
'Tel: ${restaurantInfo['contact']!}',
style: pw.TextStyle(fontSize: smallSize),
textAlign: pw.TextAlign.center,
),
pw.SizedBox(height: 3),
// Ligne de séparation
pw.Container(
width: double.infinity,
height: 0.5,
color: PdfColors.black,
),
pw.SizedBox(height: 2),
// Informations ticket
pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
children: [
pw.Text(
'Ticket: $factureNumber',
style: pw.TextStyle( style: pw.TextStyle(
fontSize: bodySize, fontSize: titleSize,
fontWeight: pw.FontWeight.bold, fontWeight: pw.FontWeight.bold,
), ),
textAlign: pw.TextAlign.center,
), ),
pw.Text( ),
'Via: ${commande.tablename ?? 'Table inconnue'}',
style: pw.TextStyle(fontSize: bodySize), pw.SizedBox(height: 1),
),
],
),
pw.SizedBox(height: 1), pw.Container(
width: double.infinity,
child: pw.Text(
restaurantInfo['adresse']!,
style: pw.TextStyle(fontSize: smallSize),
textAlign: pw.TextAlign.center,
),
),
pw.Row( pw.Container(
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, width: double.infinity,
children: [ child: pw.Text(
pw.Text( restaurantInfo['ville']!,
_formatDate(dateTime),
style: pw.TextStyle(fontSize: smallSize), style: pw.TextStyle(fontSize: smallSize),
textAlign: pw.TextAlign.center,
), ),
pw.Text( ),
_formatTime(dateTime),
pw.Container(
width: double.infinity,
child: pw.Text(
'Tel: ${restaurantInfo['contact']!}',
style: pw.TextStyle(fontSize: smallSize), style: pw.TextStyle(fontSize: smallSize),
textAlign: pw.TextAlign.center,
), ),
], ),
),
pw.SizedBox(height: 3),
pw.SizedBox(height: 2),
// Ligne de séparation
// Ligne de séparation pw.Container(
pw.Container( width: double.infinity,
width: double.infinity, height: 0.5,
height: 0.5, color: PdfColors.black,
color: PdfColors.black, ),
),
pw.SizedBox(height: 2),
pw.SizedBox(height: 2),
// Informations ticket
// Articles (format très compact) pw.Container(
...commande.items width: double.infinity,
.map( child: pw.Row(
(item) => pw.Container( mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
margin: const pw.EdgeInsets.only(bottom: 1), children: [
child: pw.Column( pw.Text(
crossAxisAlignment: pw.CrossAxisAlignment.start, 'Ticket: $factureNumber',
children: [ style: pw.TextStyle(
// Nom du plat fontSize: bodySize,
pw.Text( fontWeight: pw.FontWeight.bold,
'${item.menuNom}', ),
style: pw.TextStyle(fontSize: bodySize), ),
maxLines: 2, ],
), ),
),
// Quantité, prix unitaire et total sur une ligne
pw.Row( pw.SizedBox(height: 1),
mainAxisAlignment:
pw.MainAxisAlignment.spaceBetween, pw.Container(
children: [ width: double.infinity,
pw.Text( child: pw.Row(
'${item.quantite}x ${item.prixUnitaire.toStringAsFixed(2)}MGA', mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
style: pw.TextStyle(fontSize: smallSize), children: [
pw.Text(
_formatDate(dateTime),
style: pw.TextStyle(fontSize: smallSize),
),
pw.Text(
_formatTime(dateTime),
style: pw.TextStyle(fontSize: smallSize),
),
],
),
),
pw.SizedBox(height: 2),
// Ligne de séparation
pw.Container(
width: double.infinity,
height: 0.5,
color: PdfColors.black,
),
pw.SizedBox(height: 2),
// Articles (format très compact)
...commande.items
.map(
(item) => pw.Container(
width: double.infinity, // 🔧 Largeur complète
margin: const pw.EdgeInsets.only(bottom: 1),
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: [
// Nom du plat
pw.Container(
width: double.infinity,
child: pw.Text(
'${item.menuNom}',
style: pw.TextStyle(fontSize: bodySize),
maxLines: 2,
), ),
pw.Text( ),
'${(item.prixUnitaire * item.quantite).toStringAsFixed(2)}MGA',
style: pw.TextStyle( // Quantité, prix unitaire et total sur une ligne
fontSize: bodySize, pw.Container(
fontWeight: pw.FontWeight.bold, width: double.infinity,
), child: pw.Row(
mainAxisAlignment:
pw.MainAxisAlignment.spaceBetween,
children: [
pw.Text(
'${item.quantite}x ${item.prixUnitaire.toStringAsFixed(2)}MGA',
style: pw.TextStyle(fontSize: smallSize),
),
pw.Text(
'${(item.prixUnitaire * item.quantite).toStringAsFixed(2)}MGA',
style: pw.TextStyle(
fontSize: bodySize,
fontWeight: pw.FontWeight.bold,
),
),
],
), ),
], ),
), ],
], ),
), ),
), )
) .toList(),
.toList(),
pw.SizedBox(height: 2),
pw.SizedBox(height: 2),
// Ligne de séparation
// Ligne de séparation pw.Container(
pw.Container( width: double.infinity,
width: double.infinity, height: 0.5,
height: 0.5, color: PdfColors.black,
color: PdfColors.black, ),
),
pw.SizedBox(height: 2),
pw.SizedBox(height: 2),
// Total
// Total pw.Container(
pw.Row( width: double.infinity,
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, child: pw.Row(
children: [ mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
pw.Text( children: [
'TOTAL', pw.Text(
style: pw.TextStyle( 'TOTAL',
fontSize: titleSize, style: pw.TextStyle(
fontWeight: pw.FontWeight.bold, fontSize: titleSize,
), fontWeight: pw.FontWeight.bold,
),
),
pw.Text(
'${commande.totalTtc.toStringAsFixed(2)}MGA',
style: pw.TextStyle(
fontSize: titleSize,
fontWeight: pw.FontWeight.bold,
),
),
],
),
),
pw.SizedBox(height: 3),
// Mode de paiement
pw.Container(
width: double.infinity,
child: pw.Text(
'Paiement: ${paymentMethod.toLowerCase()}',
style: pw.TextStyle(fontSize: bodySize),
textAlign: pw.TextAlign.center,
), ),
pw.Text( ),
'${commande.totalTtc.toStringAsFixed(2)}MGA',
pw.SizedBox(height: 3),
// Ligne de séparation
pw.Container(
width: double.infinity,
height: 0.5,
color: PdfColors.black,
),
pw.SizedBox(height: 2),
// Message de remerciement
pw.Container(
width: double.infinity,
child: pw.Text(
'Merci de votre visite !',
style: pw.TextStyle( style: pw.TextStyle(
fontSize: titleSize, fontSize: bodySize,
fontWeight: pw.FontWeight.bold, fontStyle: pw.FontStyle.italic,
), ),
textAlign: pw.TextAlign.center,
), ),
],
),
pw.SizedBox(height: 3),
// Mode de paiement
pw.Text(
'Paiement: ${_getPaymentMethodText(paymentMethod)}',
style: pw.TextStyle(fontSize: bodySize),
textAlign: pw.TextAlign.center,
),
pw.SizedBox(height: 3),
// Ligne de séparation
pw.Container(
width: double.infinity,
height: 0.5,
color: PdfColors.black,
),
pw.SizedBox(height: 2),
// Message de remerciement
pw.Text(
'Merci de votre visite !',
style: pw.TextStyle(
fontSize: bodySize,
fontStyle: pw.FontStyle.italic,
), ),
textAlign: pw.TextAlign.center,
), pw.Container(
width: double.infinity,
pw.Text( child: pw.Text(
'A bientôt !', 'A bientôt !',
style: pw.TextStyle(fontSize: smallSize), style: pw.TextStyle(fontSize: smallSize),
textAlign: pw.TextAlign.center, textAlign: pw.TextAlign.center,
), ),
),
pw.SizedBox(height: 3),
pw.SizedBox(height: 3),
// Code de suivi (optionnel)
pw.Text( // Code de suivi (optionnel)
'Code: ${factureNumber}', pw.Container(
style: pw.TextStyle(fontSize: smallSize), width: double.infinity,
textAlign: pw.TextAlign.center, child: pw.Text(
), 'Code: ${factureNumber}',
style: pw.TextStyle(fontSize: smallSize),
pw.SizedBox(height: 4), textAlign: pw.TextAlign.center,
),
// Ligne de découpe ),
pw.Text(
'- - - - - - - - - - - - - - - -', pw.SizedBox(height: 4),
style: pw.TextStyle(fontSize: smallSize),
textAlign: pw.TextAlign.center, // Ligne de découpe
), pw.Container(
width: double.infinity,
pw.SizedBox(height: 2), child: pw.Text(
], '- - - - - - - - - - - - - - - -',
style: pw.TextStyle(fontSize: smallSize),
textAlign: pw.TextAlign.center,
),
),
pw.SizedBox(height: 2),
],
),
); );
}, },
), ),

82
lib/widgets/bottom_navigation.dart

@ -238,48 +238,48 @@ class AppBottomNavigation extends StatelessWidget {
), ),
), ),
const SizedBox(width: 20), // const SizedBox(width: 20),
GestureDetector( // GestureDetector(
onTap: () => onItemTapped(6), // onTap: () => onItemTapped(6),
child: Container( // child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), // padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration( // decoration: BoxDecoration(
color: // color:
selectedIndex == 5 // selectedIndex == 5
? Colors.green.shade700 // ? Colors.green.shade700
: Colors.transparent, // : Colors.transparent,
borderRadius: BorderRadius.circular(20), // borderRadius: BorderRadius.circular(20),
), // ),
child: Row( // child: Row(
mainAxisSize: MainAxisSize.min, // mainAxisSize: MainAxisSize.min,
children: [ // children: [
Icon( // Icon(
Icons.payment, // Icons.payment,
color: // color:
selectedIndex == 5 // selectedIndex == 5
? Colors.white // ? Colors.white
: Colors.grey.shade600, // : Colors.grey.shade600,
size: 16, // size: 16,
), // ),
const SizedBox(width: 6), // const SizedBox(width: 6),
Text( // Text(
'Historique', // 'Historique',
style: TextStyle( // style: TextStyle(
color: // color:
selectedIndex == 5 // selectedIndex == 5
? Colors.white // ? Colors.white
: Colors.grey.shade600, // : Colors.grey.shade600,
fontWeight: // fontWeight:
selectedIndex == 5 // selectedIndex == 5
? FontWeight.w500 // ? FontWeight.w500
: FontWeight.normal, // : FontWeight.normal,
), // ),
), // ),
], // ],
), // ),
), // ),
), // ),
const Spacer(), const Spacer(),

Loading…
Cancel
Save