import 'package:flutter/widgets.dart' show AssetImage; import 'package:pdf/pdf.dart'; import 'package:pdf/widgets.dart' as pw; import 'package:printing/printing.dart'; import '../../models/document_model.dart'; class PdfService { static Future generateAndPrintReceipt(DocumentModel document) async { final pdf = pw.Document(); // Load PFM logo asset final logoImage = await flutterImageProvider(const AssetImage('assets/logo.png')); // Add page pdf.addPage( pw.Page( pageFormat: PdfPageFormat.a4, build: (pw.Context context) { return pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ // Header & Title pw.Row( mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, children: [ pw.Text('RECEIPT OF DELIVERY', style: pw.TextStyle(fontSize: 24, fontWeight: pw.FontWeight.bold)), pw.SizedBox( width: 60, height: 60, child: pw.Image(logoImage), ), ] ), pw.SizedBox(height: 20), // Document Headers pw.Container( padding: const pw.EdgeInsets.all(10), decoration: pw.BoxDecoration( border: pw.Border.all(color: PdfColors.grey), borderRadius: const pw.BorderRadius.all(pw.Radius.circular(8)), ), child: pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ _buildTextRow('Tanggal', document.tanggal), _buildTextRow('No PO', document.noPo), _buildTextRow('No SO', document.noSo), _buildTextRow('No DO', document.noDo), ] ), ), pw.SizedBox(height: 20), // Shipment Data pw.Text('Shipment Details', style: pw.TextStyle(fontSize: 16, fontWeight: pw.FontWeight.bold)), pw.SizedBox(height: 8), pw.Container( padding: const pw.EdgeInsets.all(10), decoration: pw.BoxDecoration( color: PdfColors.grey100, borderRadius: const pw.BorderRadius.all(pw.Radius.circular(8)), ), child: pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ _buildTextRow('Kepada Yth', document.kepadaYth), _buildTextRow('Order Untuk', document.orderUntuk), _buildTextRow('Alamat', document.alamat), _buildTextRow('Plat Truk', document.platTruk), _buildTextRow('Nama Driver', document.namaDriver), ] ), ), pw.SizedBox(height: 20), // Items Table pw.Text('Items Delivered', style: pw.TextStyle(fontSize: 16, fontWeight: pw.FontWeight.bold)), pw.SizedBox(height: 8), pw.Table.fromTextArray( context: context, border: pw.TableBorder.all(color: PdfColors.grey), headerDecoration: const pw.BoxDecoration(color: PdfColors.grey300), headerHeight: 25, cellHeight: 25, columnWidths: { 0: const pw.FixedColumnWidth(80), // SKU 1: const pw.FlexColumnWidth(2), // Nama Barang 2: const pw.FixedColumnWidth(70), // Banyak 3: const pw.FixedColumnWidth(70), // Jumlah }, cellAlignments: { 0: pw.Alignment.centerLeft, 1: pw.Alignment.centerLeft, 2: pw.Alignment.centerRight, 3: pw.Alignment.centerRight, }, headers: ['Nomor SKU', 'Nama Barang', 'Banyak', 'Jumlah'], data: document.items.map((item) { return [ item.nomorSku, item.namaBarang, item.banyak, item.jumlah, ]; }).toList(), ), pw.Spacer(), // Footer & Signatures pw.Row( mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, children: [ pw.Column( children: [ pw.SizedBox(height: 40), pw.Text(document.namaDriver.isNotEmpty ? document.namaDriver : '_______________________', style: pw.TextStyle(fontWeight: pw.FontWeight.bold)), pw.SizedBox(height: 4), pw.Text('Pengirim (Driver)'), ] ), pw.Column( children: [ pw.SizedBox(height: 40), pw.Text(document.namaPenerima.isNotEmpty ? document.namaPenerima : '_______________________', style: pw.TextStyle(fontWeight: pw.FontWeight.bold)), pw.SizedBox(height: 4), pw.Text('Penerima (Penjaga Toko)'), ] ) ] ) ], ); }, ), ); // Prompt user to view/print/save the PDF natively await Printing.layoutPdf( onLayout: (PdfPageFormat format) async => pdf.save(), format: PdfPageFormat.a4, name: 'Document_${document.noDo.replaceAll('/', '_')}', ); } static pw.Widget _buildTextRow(String label, String value) { return pw.Padding( padding: const pw.EdgeInsets.symmetric(vertical: 2), child: pw.Row( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ pw.SizedBox(width: 100, child: pw.Text(label, style: pw.TextStyle(fontWeight: pw.FontWeight.bold))), pw.Expanded( child: pw.Text(': $value', softWrap: true), ), ] ) ); } }