752 lines
26 KiB
Dart
752 lines
26 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:praresi/presentation/routes/app_routes.dart';
|
|
import 'package:praresi/utils/pdf_export_daily_a4.dart';
|
|
import 'package:praresi/utils/pdf_export_daily_a4_multi.dart';
|
|
import 'package:praresi/utils/pdf_export_daily_a5.dart';
|
|
import 'package:praresi/utils/pdf_export_daily_a5_multi.dart';
|
|
import 'package:praresi/utils/pdf_export_daily_a6.dart';
|
|
import '../controllers/riwayat_controller.dart';
|
|
|
|
class RiwayatView extends StatefulWidget {
|
|
const RiwayatView({super.key});
|
|
|
|
@override
|
|
State<RiwayatView> createState() => _RiwayatViewState();
|
|
}
|
|
|
|
class _RiwayatViewState extends State<RiwayatView> {
|
|
DateTime? startDate;
|
|
DateTime? endDate;
|
|
final riwayatC = Get.put(RiwayatController(), permanent: true);
|
|
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
final now = DateTime.now();
|
|
startDate = DateTime(now.year, now.month, 1);
|
|
endDate = DateTime(now.year, now.month + 1, 0, 23, 59, 59);
|
|
riwayatC.fetchResiData(); // 🔹 ambil data default (1 bulan terakhir)
|
|
}
|
|
|
|
Future<void> _selectDate(bool isStart) async {
|
|
final now = DateTime.now();
|
|
|
|
final picked = await showDatePicker(
|
|
context: context,
|
|
initialDate: isStart
|
|
? (startDate ?? DateTime(now.year, now.month, 1))
|
|
: (endDate ?? DateTime(now.year, now.month + 1, 0)),
|
|
firstDate: DateTime(2023),
|
|
lastDate: DateTime(2100),
|
|
builder: (context, child) => Theme(
|
|
data: Theme.of(context).copyWith(
|
|
colorScheme: const ColorScheme.light(
|
|
primary: Color(0xFF1976D2),
|
|
onPrimary: Colors.white,
|
|
onSurface: Colors.black,
|
|
),
|
|
),
|
|
child: child!,
|
|
),
|
|
);
|
|
|
|
if (picked != null) {
|
|
setState(() {
|
|
if (isStart) {
|
|
startDate = DateTime(picked.year, picked.month, picked.day);
|
|
} else {
|
|
// ⏰ tambahkan jam agar mencakup full hari terakhir
|
|
endDate = DateTime(picked.year, picked.month, picked.day, 23, 59, 59);
|
|
}
|
|
});
|
|
|
|
// 🔹 Kalau dua-duanya sudah terisi, ambil data
|
|
if (startDate != null && endDate != null) {
|
|
riwayatC.fetchResiData(start: startDate, end: endDate);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final size = MediaQuery.of(context).size;
|
|
|
|
return Scaffold(
|
|
body: Container(
|
|
width: size.width,
|
|
height: size.height,
|
|
decoration: const BoxDecoration(
|
|
gradient: LinearGradient(
|
|
colors: [Color(0xFF1976D2), Color(0xFFE3F2FD)],
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
),
|
|
),
|
|
child: SafeArea(
|
|
child: Column(
|
|
children: [
|
|
// 🔹 Card filter tanggal
|
|
Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(20),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, 4),
|
|
),
|
|
],
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
child: _dateInputCard(
|
|
label: "Mulai dari",
|
|
date: startDate,
|
|
onTap: () => _selectDate(true),
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: _dateInputCard(
|
|
label: "Hingga",
|
|
date: endDate,
|
|
onTap: () => _selectDate(false),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
// 🔹 Garis pembatas putih dari kiri ke kanan
|
|
const Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 16),
|
|
child: Divider(
|
|
color: Colors.white, // warna garis
|
|
thickness: 1, // ketebalan garis
|
|
),
|
|
),
|
|
|
|
// 🔹 Daftar data dari Firestore
|
|
Expanded(
|
|
child: Obx(() {
|
|
if (riwayatC.isLoading.value) {
|
|
return const Center(
|
|
child:
|
|
CircularProgressIndicator(color: Color(0xFF1976D2)),
|
|
);
|
|
}
|
|
|
|
if (riwayatC.dailySummary.isEmpty) {
|
|
return const Center(
|
|
child: Text(
|
|
"Belum ada data resi",
|
|
style: TextStyle(color: Colors.black54, fontSize: 16),
|
|
),
|
|
);
|
|
}
|
|
|
|
return SingleChildScrollView(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 16, vertical: 10),
|
|
child: Column(
|
|
children: riwayatC.dailySummary.map((data) {
|
|
return Padding(
|
|
padding: const EdgeInsets.only(bottom: 15),
|
|
child: _dailySummaryCard(
|
|
day: data['day'],
|
|
date: data['date'],
|
|
total: data['total'],
|
|
cod: data['cod'],
|
|
nonCod: data['nonCod'],
|
|
income: data['income'],
|
|
),
|
|
);
|
|
}).toList(),
|
|
),
|
|
);
|
|
}),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 🔹 Widget input tanggal
|
|
Widget _dateInputCard({
|
|
required String label,
|
|
required DateTime? date,
|
|
required VoidCallback onTap,
|
|
}) {
|
|
return GestureDetector(
|
|
onTap: onTap,
|
|
child: Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(14),
|
|
border: Border.all(color: Colors.grey.shade300),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(label,
|
|
style: const TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.grey,
|
|
fontWeight: FontWeight.w500,
|
|
)),
|
|
const SizedBox(height: 4),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(
|
|
date == null
|
|
? "Pilih tanggal"
|
|
: DateFormat('dd MMM yyyy', 'id_ID').format(date),
|
|
style: const TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.black87,
|
|
),
|
|
),
|
|
const Icon(Icons.calendar_today,
|
|
color: Color(0xFF1976D2), size: 18),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 🔹 Widget tampilan per hari (sesuai desain kamu)
|
|
Widget _dailySummaryCard({
|
|
required String day,
|
|
required String date,
|
|
required int total,
|
|
required int cod,
|
|
required int nonCod,
|
|
required int income,
|
|
}) {
|
|
return GestureDetector(
|
|
onTap: () async {
|
|
final controller = Get.find<RiwayatController>();
|
|
try {
|
|
// ubah format tanggal "21 Oktober 2025" ke DateTime
|
|
final rawDate = DateFormat('d MMMM yyyy', 'id_ID').parse(date);
|
|
|
|
// tampilkan snackbar loading sementara
|
|
Get.snackbar(
|
|
'Memuat',
|
|
'Mengambil data detail...',
|
|
showProgressIndicator: true,
|
|
isDismissible: false,
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
);
|
|
|
|
// ambil data dulu
|
|
await controller.fetchResiByDate(rawDate);
|
|
|
|
// tutup snackbar
|
|
Get.closeAllSnackbars();
|
|
|
|
// navigasi ke halaman detail (pakai named route)
|
|
Get.toNamed(
|
|
AppRoutes.detailRiwayat,
|
|
arguments: {
|
|
'day': day,
|
|
'date': date,
|
|
},
|
|
);
|
|
} catch (e) {
|
|
Get.closeAllSnackbars();
|
|
Get.snackbar('Error', 'Gagal membuka detail: $e');
|
|
}
|
|
},
|
|
|
|
|
|
child: Container(
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.all(18),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(20),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.08),
|
|
blurRadius: 8,
|
|
offset: const Offset(0, 5),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// 🔹 Baris header: hari & tanggal + ikon print di kanan atas
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(
|
|
"$day, $date",
|
|
style: const TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.black87,
|
|
),
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.download, color: Color(0xFF1976D2)),
|
|
tooltip: "Unduh data hari ini",
|
|
onPressed: () {
|
|
_showPrintFormatDialog(context, day, date, riwayatC);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
|
|
const Divider(),
|
|
const SizedBox(height: 5),
|
|
|
|
// 🔸 Total paket dan COD/NON-COD
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Expanded(
|
|
flex: 2,
|
|
child: Container(
|
|
height: 90,
|
|
margin: const EdgeInsets.only(right: 10),
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: const Color(0xFF1976D2), width: 2),
|
|
borderRadius: BorderRadius.circular(14),
|
|
),
|
|
child: Center(
|
|
child: Text(
|
|
"Total \n$total",
|
|
textAlign: TextAlign.center,
|
|
style: const TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.bold,
|
|
color: Color(0xFF1976D2),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 2,
|
|
child: Column(
|
|
children: [
|
|
// 🔹 Card COD
|
|
InkWell(
|
|
onTap: () async {
|
|
final rawDate = DateFormat('d MMMM yyyy', 'id_ID').parse(date);
|
|
final pendapatan =
|
|
await riwayatC.getPendapatanHarian(rawDate);
|
|
final totalCod = pendapatan['cod'] ?? 0.0;
|
|
|
|
Get.defaultDialog(
|
|
title: "Pendapatan COD",
|
|
titleStyle: const TextStyle(
|
|
color: Color(0xFFFF9800),
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 18,
|
|
),
|
|
contentPadding: const EdgeInsets.symmetric(
|
|
horizontal: 20, vertical: 16),
|
|
radius: 14,
|
|
content: Column(
|
|
children: [
|
|
Icon(Icons.local_shipping,
|
|
color: const Color(0xFFFF9800), size: 48),
|
|
const SizedBox(height: 12),
|
|
Text(
|
|
"Tanggal: ${DateFormat('d MMMM yyyy', 'id_ID').format(rawDate)}",
|
|
style: const TextStyle(fontSize: 14),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
"Rp ${NumberFormat('#,###', 'id_ID').format(totalCod)}",
|
|
style: const TextStyle(
|
|
fontSize: 22,
|
|
fontWeight: FontWeight.bold,
|
|
color: Color(0xFFFF9800),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
confirm: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: const Color(0xFFFF9800),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 20, vertical: 10),
|
|
),
|
|
onPressed: () => Get.back(),
|
|
child: const Text(
|
|
"Tutup",
|
|
style: TextStyle(color: Colors.white),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
child: Container(
|
|
height: 40,
|
|
margin: const EdgeInsets.only(bottom: 10),
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: const Color(0xFFFF9800), width: 2),
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Center(
|
|
child: Text(
|
|
"COD: $cod",
|
|
style: const TextStyle(
|
|
color: Color(0xFFFF9800),
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
// 🔹 Card Non COD
|
|
InkWell(
|
|
onTap: () async {
|
|
final rawDate = DateFormat('d MMMM yyyy', 'id_ID').parse(date);
|
|
final pendapatan =
|
|
await riwayatC.getPendapatanHarian(rawDate);
|
|
final totalNonCod = pendapatan['nonCod'] ?? 0.0;
|
|
|
|
Get.defaultDialog(
|
|
title: "Pendapatan Non COD",
|
|
titleStyle: const TextStyle(
|
|
color: Color(0xFF4CAF50),
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 18,
|
|
),
|
|
contentPadding: const EdgeInsets.symmetric(
|
|
horizontal: 20, vertical: 16),
|
|
radius: 14,
|
|
content: Column(
|
|
children: [
|
|
Icon(Icons.account_balance_wallet,
|
|
color: const Color(0xFF4CAF50), size: 48),
|
|
const SizedBox(height: 12),
|
|
Text(
|
|
"Tanggal: ${DateFormat('d MMMM yyyy', 'id_ID').format(rawDate)}",
|
|
style: const TextStyle(fontSize: 14),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
"Rp ${NumberFormat('#,###', 'id_ID').format(totalNonCod)}",
|
|
style: const TextStyle(
|
|
fontSize: 22,
|
|
fontWeight: FontWeight.bold,
|
|
color: Color(0xFF4CAF50),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
confirm: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: const Color(0xFF4CAF50),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 20, vertical: 10),
|
|
),
|
|
onPressed: () => Get.back(),
|
|
child: const Text(
|
|
"Tutup",
|
|
style: TextStyle(color: Colors.white),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
child: Container(
|
|
height: 40,
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: const Color(0xFF4CAF50), width: 2),
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Center(
|
|
child: Text(
|
|
"Non COD: $nonCod",
|
|
style: const TextStyle(
|
|
color: Color(0xFF4CAF50),
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
|
|
|
|
|
|
const SizedBox(height: 10),
|
|
|
|
// 🔸 Pendapatan
|
|
Container(
|
|
width: double.infinity,
|
|
height: 40,
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: Colors.grey.shade400, width: 1.2),
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Center(
|
|
child: Text(
|
|
"Rp ${NumberFormat('#,###', 'id_ID').format(income)}",
|
|
style: const TextStyle(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.black87,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
|
|
void _showPrintFormatDialog(BuildContext context, String day, String date, dynamic controller,) {
|
|
Get.bottomSheet(
|
|
Container(
|
|
padding: const EdgeInsets.all(20),
|
|
decoration: const BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
|
),
|
|
child: Wrap(
|
|
children: [
|
|
const Center(
|
|
child: Text(
|
|
"Pilih Format Unduh",
|
|
style: TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
ListTile(
|
|
leading: const Icon(Icons.picture_as_pdf, color: Colors.blue),
|
|
title: const Text("Format A4"),
|
|
onTap: () async {
|
|
Get.back();
|
|
|
|
try {
|
|
// 🔹 Parse tanggal
|
|
final parsedDate =
|
|
DateFormat('d MMMM yyyy', 'id_ID').parse(date);
|
|
|
|
// 🔹 Ambil data harian
|
|
await controller.fetchResiByDate(parsedDate);
|
|
|
|
// 🔹 Export PDF (1 halaman = 1 data)
|
|
final path = await PdfExportDailyA4_onedata.exportDailyToA4_onedata(
|
|
controller.dailyDetail,
|
|
parsedDate,
|
|
);
|
|
|
|
Get.snackbar(
|
|
"Berhasil",
|
|
"PDF disimpan di: $path",
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
backgroundColor: Colors.green.shade100,
|
|
);
|
|
} catch (e) {
|
|
Get.snackbar(
|
|
"Error",
|
|
"Gagal mencetak data: $e",
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
backgroundColor: Colors.red.shade100,
|
|
);
|
|
}
|
|
},
|
|
),
|
|
|
|
ListTile(
|
|
leading: const Icon(Icons.picture_as_pdf, color: Colors.blue),
|
|
title: const Text("Format A5"),
|
|
onTap: () async {
|
|
Get.back();
|
|
|
|
try {
|
|
// 🔹 Parse tanggal "25 Oktober 2025" ke DateTime
|
|
final parsedDate =
|
|
DateFormat('d MMMM yyyy', 'id_ID').parse(date);
|
|
|
|
// 🔹 Ambil data harian
|
|
await controller.fetchResiByDate(parsedDate);
|
|
|
|
// 🔹 Cetak ke PDF format A4
|
|
final path = await PdfExportDailyA5_onedata.exportDailyToA5_onedata(
|
|
controller.dailyDetail,
|
|
parsedDate,
|
|
);
|
|
|
|
Get.snackbar(
|
|
"Berhasil",
|
|
"PDF disimpan di: $path",
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
backgroundColor: Colors.green.shade100,
|
|
);
|
|
} catch (e) {
|
|
Get.snackbar(
|
|
"Error",
|
|
"Gagal mencetak data: $e",
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
backgroundColor: Colors.red.shade100,
|
|
);
|
|
}
|
|
},
|
|
),
|
|
|
|
ListTile(
|
|
leading: const Icon(Icons.picture_as_pdf, color: Colors.blue),
|
|
title: const Text("Format A6"),
|
|
onTap: () async {
|
|
Get.back();
|
|
|
|
try {
|
|
// 🔹 Parse tanggal "25 Oktober 2025" ke DateTime
|
|
final parsedDate =
|
|
DateFormat('d MMMM yyyy', 'id_ID').parse(date);
|
|
|
|
// 🔹 Ambil data harian
|
|
await controller.fetchResiByDate(parsedDate);
|
|
|
|
// 🔹 Cetak ke PDF format A4
|
|
final path = await PdfExportDailyA6.exportDailyToA6(
|
|
controller.dailyDetail,
|
|
parsedDate,
|
|
);
|
|
|
|
Get.snackbar(
|
|
"Berhasil",
|
|
"PDF disimpan di: $path",
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
backgroundColor: Colors.green.shade100,
|
|
);
|
|
} catch (e) {
|
|
Get.snackbar(
|
|
"Error",
|
|
"Gagal mengunduh data: $e",
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
backgroundColor: Colors.red.shade100,
|
|
);
|
|
}
|
|
},
|
|
),
|
|
|
|
ListTile(
|
|
leading: const Icon(Icons.picture_as_pdf, color: Colors.blue),
|
|
title: const Text("Format A4 (Multi)"),
|
|
onTap: () async {
|
|
Get.back();
|
|
|
|
try {
|
|
// 🔹 Parse tanggal "25 Oktober 2025" ke DateTime
|
|
final parsedDate =
|
|
DateFormat('d MMMM yyyy', 'id_ID').parse(date);
|
|
|
|
// 🔹 Ambil data harian
|
|
await controller.fetchResiByDate(parsedDate);
|
|
|
|
// 🔹 Cetak ke PDF format A4
|
|
final path = await PdfExportDailyA4.exportDailyToA4(
|
|
controller.dailyDetail,
|
|
parsedDate,
|
|
);
|
|
|
|
Get.snackbar(
|
|
"Berhasil",
|
|
"PDF disimpan di: $path",
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
backgroundColor: Colors.green.shade100,
|
|
);
|
|
} catch (e) {
|
|
Get.snackbar(
|
|
"Error",
|
|
"Gagal mencetak data: $e",
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
backgroundColor: Colors.red.shade100,
|
|
);
|
|
}
|
|
},
|
|
),
|
|
|
|
|
|
|
|
|
|
ListTile(
|
|
leading: const Icon(Icons.picture_as_pdf, color: Colors.blue),
|
|
title: const Text("Format A5 (Multi)"),
|
|
onTap: () async {
|
|
Get.back();
|
|
|
|
try {
|
|
// 🔹 Parse tanggal "25 Oktober 2025" ke DateTime
|
|
final parsedDate =
|
|
DateFormat('d MMMM yyyy', 'id_ID').parse(date);
|
|
|
|
// 🔹 Ambil data harian
|
|
await controller.fetchResiByDate(parsedDate);
|
|
|
|
// 🔹 Cetak ke PDF format A4
|
|
final path = await PdfExportDailyA5.exportDailyToA5(
|
|
controller.dailyDetail,
|
|
parsedDate,
|
|
);
|
|
|
|
Get.snackbar(
|
|
"Berhasil",
|
|
"PDF disimpan di: $path",
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
backgroundColor: Colors.green.shade100,
|
|
);
|
|
} catch (e) {
|
|
Get.snackbar(
|
|
"Error",
|
|
"Gagal mencetak data: $e",
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
backgroundColor: Colors.red.shade100,
|
|
);
|
|
}
|
|
},
|
|
),
|
|
|
|
|
|
|
|
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
}
|