// lib/screens/saved_reports_screen.dart import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:cashumit/models/saved_report.dart'; import 'package:cashumit/services/saved_report_service.dart'; import 'package:cashumit/screens/report_screen.dart'; import 'package:cashumit/utils/currency_format.dart'; class SavedReportsScreen extends StatefulWidget { const SavedReportsScreen({super.key}); @override State createState() => _SavedReportsScreenState(); } class _SavedReportsScreenState extends State { List _reports = []; bool _isLoading = true; @override void initState() { super.initState(); _loadReports(); } Future _loadReports() async { setState(() => _isLoading = true); final list = await SavedReportService.getAllReports(); if (mounted) { setState(() { _reports = list; _isLoading = false; }); } } Future _openReport(SavedReport report) async { await Navigator.push( context, MaterialPageRoute( builder: (context) => ReportScreen(savedReport: report), ), ); // Muat ulang setelah kembali dari layar laporan _loadReports(); } Future _deleteReport(SavedReport report) async { final confirm = await showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('Hapus Laporan Tersimpan?'), content: Text( 'Apakah Anda yakin ingin menghapus draft "${report.title}"? Tindakan ini tidak dapat dibatalkan.', ), actions: [ TextButton( onPressed: () => Navigator.pop(ctx, false), child: const Text('Batal'), ), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.red, foregroundColor: Colors.white, ), onPressed: () => Navigator.pop(ctx, true), child: const Text('Hapus'), ), ], ), ); if (confirm == true) { final success = await SavedReportService.deleteReport(report.id); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( success ? 'Draft "${report.title}" berhasil dihapus' : 'Gagal menghapus draft', ), ), ); _loadReports(); } } } @override Widget build(BuildContext context) { final primaryColor = Theme.of(context).colorScheme.primary; final dateFmt = DateFormat('dd MMM yyyy'); final timeFmt = DateFormat('dd MMM yyyy, HH:mm'); return Scaffold( appBar: AppBar( title: const Text( 'Laporan Tersimpan', style: TextStyle(fontWeight: FontWeight.bold), ), backgroundColor: primaryColor, foregroundColor: Colors.white, actions: [ IconButton( icon: const Icon(Icons.refresh), tooltip: 'Segarkan', onPressed: _loadReports, ), ], ), body: _isLoading ? const Center(child: CircularProgressIndicator()) : _reports.isEmpty ? _buildEmptyState() : RefreshIndicator( onRefresh: _loadReports, child: ListView.builder( padding: const EdgeInsets.all(12), itemCount: _reports.length, itemBuilder: (context, index) { final r = _reports[index]; return _buildReportCard(r, dateFmt, timeFmt); }, ), ), floatingActionButton: FloatingActionButton.extended( backgroundColor: primaryColor, foregroundColor: Colors.white, icon: const Icon(Icons.add), label: const Text('Buat Laporan Baru'), onPressed: () async { await Navigator.push( context, MaterialPageRoute( builder: (context) => const ReportScreen(), ), ); _loadReports(); }, ), ); } Widget _buildEmptyState() { return Center( child: Padding( padding: const EdgeInsets.all(32), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.folder_open_outlined, size: 72, color: Colors.grey.shade400), const SizedBox(height: 16), const Text( 'Belum Ada Laporan Tersimpan', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 8), Text( 'Ketika membuat laporan keuangan, Anda dapat menyimpannya sebagai draft untuk dilanjutkan atau dicetak kemudian.', textAlign: TextAlign.center, style: TextStyle(fontSize: 13, color: Colors.grey.shade600), ), const SizedBox(height: 24), ElevatedButton.icon( icon: const Icon(Icons.add), label: const Text('Buat Laporan Sekarang'), onPressed: () async { await Navigator.push( context, MaterialPageRoute( builder: (context) => const ReportScreen(), ), ); _loadReports(); }, ), ], ), ), ); } Widget _buildReportCard( SavedReport r, DateFormat dateFmt, DateFormat timeFmt, ) { final allComplete = r.incompleteAttachmentCount == 0; return Card( margin: const EdgeInsets.only(bottom: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide(color: Colors.grey.shade200), ), elevation: 2, child: Padding( padding: const EdgeInsets.all(14), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Baris Judul & Aksi Hapus Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( r.title, style: const TextStyle( fontSize: 15, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4), Row( children: [ Icon(Icons.account_balance_wallet_outlined, size: 14, color: Colors.grey.shade600), const SizedBox(width: 4), Text( r.accountName, style: TextStyle( fontSize: 12, color: Colors.grey.shade700, fontWeight: FontWeight.w500, ), ), ], ), const SizedBox(height: 2), Row( children: [ Icon(Icons.calendar_today_outlined, size: 13, color: Colors.grey.shade600), const SizedBox(width: 4), Text( '${dateFmt.format(r.startDate)} - ${dateFmt.format(r.endDate)}', style: TextStyle( fontSize: 12, color: Colors.grey.shade600, ), ), ], ), ], ), ), IconButton( icon: const Icon(Icons.delete_outline, color: Colors.red, size: 20), tooltip: 'Hapus Draft', onPressed: () => _deleteReport(r), ), ], ), const Divider(height: 18), // Ringkasan Keuangan Row( children: [ Expanded( child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: const Color(0xFFF0FDF4), borderRadius: BorderRadius.circular(6), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Masuk', style: TextStyle(fontSize: 10, color: Color(0xFF166534))), FittedBox( fit: BoxFit.scaleDown, child: Text( CurrencyFormat.formatRupiah(r.totalPemasukan), style: const TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Color(0xFF166534), ), ), ), ], ), ), ), const SizedBox(width: 6), Expanded( child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: const Color(0xFFFEF2F2), borderRadius: BorderRadius.circular(6), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Keluar', style: TextStyle(fontSize: 10, color: Color(0xFF991B1B))), FittedBox( fit: BoxFit.scaleDown, child: Text( CurrencyFormat.formatRupiah(r.totalPengeluaran), style: const TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Color(0xFF991B1B), ), ), ), ], ), ), ), const SizedBox(width: 6), Expanded( child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: const Color(0xFFF8FAFC), borderRadius: BorderRadius.circular(6), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Saldo', style: TextStyle(fontSize: 10, color: Color(0xFF334155))), FittedBox( fit: BoxFit.scaleDown, child: Text( CurrencyFormat.formatRupiah(r.saldoBersih), style: const TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Color(0xFF334155), ), ), ), ], ), ), ), ], ), const SizedBox(height: 10), // Status Lampiran & Tanggal Diperbarui Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: allComplete ? const Color(0xFFDCFCE7) : const Color(0xFFFEF3C7), borderRadius: BorderRadius.circular(12), ), child: Text( allComplete ? 'Semua bukti lengkap (${r.transactions.length} transaksi)' : '${r.completedAttachmentCount}/${r.totalPengeluaranCount} bukti pengeluaran', style: TextStyle( fontSize: 11, fontWeight: FontWeight.bold, color: allComplete ? const Color(0xFF166534) : const Color(0xFFB45309), ), ), ), Text( timeFmt.format(r.updatedAt), style: TextStyle(fontSize: 10.5, color: Colors.grey.shade500), ), ], ), const SizedBox(height: 12), // Tombol Buka / Lanjutkan Edit SizedBox( width: double.infinity, height: 38, child: ElevatedButton.icon( style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF16A34A), foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), icon: const Icon(Icons.edit_document, size: 16), label: const Text('Buka / Lanjutkan Edit', style: TextStyle(fontSize: 12.5)), onPressed: () => _openReport(r), ), ), ], ), ), ); } }