import 'dart:io'; import 'package:flutter/material.dart'; import 'package:pdf/widgets.dart' as pw; import 'package:path_provider/path_provider.dart'; import 'package:share_plus/share_plus.dart'; class ExportService { static final ExportService _instance = ExportService._internal(); factory ExportService() => _instance; ExportService._internal(); Future exportToPdf(List> transactions, String storeName, DateTimeRange? dateRange) async { try { debugPrint('exportToPdf called with ${transactions.length} transactions'); final pdf = pw.Document(); pdf.addPage( pw.Page( build: (context) { return pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ pw.Text(storeName, style: pw.TextStyle(fontSize: 24, fontWeight: pw.FontWeight.bold)), pw.SizedBox(height: 8), if (dateRange != null) pw.Text('${_formatDate(dateRange.start)} - ${_formatDate(dateRange.end)}', style: pw.TextStyle(fontSize: 12)), pw.SizedBox(height: 16), pw.Table( border: pw.TableBorder.all(), children: [ pw.TableRow( children: [ pw.Padding(padding: pw.EdgeInsets.all(8), child: pw.Text('Tanggal', style: pw.TextStyle(fontWeight: pw.FontWeight.bold))), pw.Padding(padding: pw.EdgeInsets.all(8), child: pw.Text('ID', style: pw.TextStyle(fontWeight: pw.FontWeight.bold))), pw.Padding(padding: pw.EdgeInsets.all(8), child: pw.Text('Total', style: pw.TextStyle(fontWeight: pw.FontWeight.bold))), pw.Padding(padding: pw.EdgeInsets.all(8), child: pw.Text('Bayar', style: pw.TextStyle(fontWeight: pw.FontWeight.bold))), pw.Padding(padding: pw.EdgeInsets.all(8), child: pw.Text('Kembali', style: pw.TextStyle(fontWeight: pw.FontWeight.bold))), ], ), for (final tx in transactions) pw.TableRow( children: [ pw.Padding(padding: const pw.EdgeInsets.all(8), child: pw.Text(_formatDate(tx['date']))), pw.Padding(padding: const pw.EdgeInsets.all(8), child: pw.Text(tx['id'])), pw.Padding(padding: const pw.EdgeInsets.all(8), child: pw.Text(tx['total'])), pw.Padding(padding: const pw.EdgeInsets.all(8), child: pw.Text(tx['paid'])), pw.Padding(padding: const pw.EdgeInsets.all(8), child: pw.Text(tx['change'])), ], ), ], ), ], ); }, ), ); Directory? directory; try { directory = await getTemporaryDirectory(); debugPrint('PDF using temporary directory: ${directory.path}'); } catch (e) { debugPrint('getTemporaryDirectory failed for PDF: $e'); return null; } final file = File('${directory.path}/laporan_transaksi_${DateTime.now().millisecondsSinceEpoch}.pdf'); try { await file.writeAsBytes(await pdf.save()); debugPrint('PDF file written: ${file.path}, exists: ${await file.exists()}'); } catch (e) { debugPrint('Failed to write PDF file: $e'); return null; } return file.path; } catch (e) { debugPrint('exportToPdf error: $e'); return null; } } Future exportToCsv(List> transactions) async { try { debugPrint('=== CSV Export Started ==='); debugPrint('Transactions count: ${transactions.length}'); if (transactions.isEmpty) { debugPrint('No transactions to export'); return null; } final buffer = StringBuffer(); buffer.writeln('Tanggal,ID Transaksi,Total,Bayar,Kembali,Item,Diskon'); for (final tx in transactions) { final date = _formatDate(tx['date']); final id = tx['id']; final total = tx['total']; final paid = tx['paid']; final change = tx['change']; final items = tx['items'] is List ? (tx['items'] as List).length : (tx['items'] as int? ?? 0); final discount = tx['discount'] ?? 0; buffer.writeln('$date,$id,$total,$paid,$change,$items,$discount'); } debugPrint('CSV buffer created, length: ${buffer.toString().length}'); String? filePath; try { final tempDir = await getTemporaryDirectory(); debugPrint('Temp dir: ${tempDir.path}'); final timestamp = DateTime.now().millisecondsSinceEpoch; final fileName = 'laporan_transaksi_$timestamp.csv'; filePath = '${tempDir.path}/$fileName'; final file = File(filePath); await file.writeAsString(buffer.toString()); debugPrint('CSV file written: $filePath'); debugPrint('File exists: ${await file.exists()}'); debugPrint('File size: ${await file.length()}'); } catch (e) { debugPrint('Error creating CSV file: $e'); return null; } debugPrint('=== CSV Export Completed Successfully ==='); return filePath; } catch (e) { debugPrint('=== CSV Export Failed ==='); debugPrint('Error: $e'); debugPrint('Stack trace: ${StackTrace.current}'); return null; } } Future shareFile(String filePath) async { try { debugPrint('Sharing file: $filePath'); final file = File(filePath); final exists = await file.exists(); debugPrint('File exists: $exists, size: ${exists ? await file.length() : 0}'); if (!exists) { debugPrint('File does not exist, cannot share'); return; } await Share.shareXFiles([XFile(filePath)], text: 'Laporan Transaksi'); debugPrint('Share completed'); } catch (e) { debugPrint('shareFile error: $e'); rethrow; } } String _formatDate(dynamic date) { if (date is DateTime) { return '${date.day}/${date.month}/${date.year}'; } return date.toString(); } }