import 'dart:typed_data'; import 'package:pdf/pdf.dart'; import 'package:pdf/widgets.dart' as pw; import '../models/produit.dart'; /// Génère une planche A4 d'étiquettes de prix (nom, prix TTC, prix HT, code-barres), /// imprimable sur une imprimante classique (ex : Canon TS4550). class EtiquettePdf { /// Construit le document PDF pour les [produits] sélectionnés. static Future construire(List produits) async { final doc = pw.Document(); doc.addPage( pw.MultiPage( pageFormat: PdfPageFormat.a4, margin: const pw.EdgeInsets.all(12), build: (context) { return [ pw.Wrap( spacing: 6, runSpacing: 6, children: produits.map(_etiquette).toList(), ), ]; }, ), ); return doc.save(); } static pw.Widget _etiquette(Produit p) { // 3 colonnes sur A4 (~186mm utiles / 3 ≈ 62mm). const largeur = 185.0; // points (~65mm) const hauteur = 110.0; // points (~39mm) return pw.Container( width: largeur, height: hauteur, padding: const pw.EdgeInsets.all(8), decoration: pw.BoxDecoration( border: pw.Border.all(color: PdfColors.grey400, width: 0.7), borderRadius: pw.BorderRadius.circular(6), ), child: pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, children: [ pw.Text( p.titre, maxLines: 2, overflow: pw.TextOverflow.clip, style: pw.TextStyle(fontSize: 10, fontWeight: pw.FontWeight.bold), ), pw.Container( width: double.infinity, alignment: pw.Alignment.center, child: pw.Column( mainAxisSize: pw.MainAxisSize.min, crossAxisAlignment: pw.CrossAxisAlignment.center, children: [ pw.Text( _prix(p.prix), style: pw.TextStyle( fontSize: 22, fontWeight: pw.FontWeight.bold), ), if (p.prixMesure != null) pw.Text( _prixMesure(p), style: const pw.TextStyle( fontSize: 9, color: PdfColors.grey700), ), ], ), ), _codeBarres(p.codeBarres), ], ), ); } static pw.Widget _codeBarres(String? code) { if (code == null || code.isEmpty) { return pw.SizedBox(height: 22); } final estEan13 = code.length == 13 && int.tryParse(code) != null; return pw.BarcodeWidget( barcode: estEan13 ? pw.Barcode.ean13() : pw.Barcode.code128(), data: code, width: 150, height: 26, drawText: true, textStyle: const pw.TextStyle(fontSize: 6), ); } static String _prix(double v) => '${v.toStringAsFixed(2).replaceAll('.', ',')} EUR'; static String _prixMesure(Produit p) { final m = p.prixMesure!; final unite = m.suffixe == '/kg' ? 'kg' : 'L'; return 'soit ${m.valeur.toStringAsFixed(2).replaceAll('.', ',')} EUR / $unite'; } }