'use client' import Logo from '@/@core/svg/Logo' import { useProductSalesAnalytics, useProfitLossAnalytics, useSalesAnalytics } from '@/services/queries/analytics' import { useOutletById } from '@/services/queries/outlets' import { formatCurrency, formatDate, formatDateDDMMYYYY, formatDatetime } from '@/utils/transform' import React, { useEffect, useRef, useState } from 'react' const DailyPOSReport = () => { const reportRef = useRef(null) const [now, setNow] = useState(new Date()) const { data: outlet } = useOutletById() const { data: sales } = useSalesAnalytics({ date_from: formatDateDDMMYYYY(now), date_to: formatDateDDMMYYYY(now) }) const { data: profitLoss } = useProfitLossAnalytics({ date_from: formatDateDDMMYYYY(now), date_to: formatDateDDMMYYYY(now) }) const { data: products } = useProductSalesAnalytics({ date_from: formatDateDDMMYYYY(now), date_to: formatDateDDMMYYYY(now) }) const user = (() => { try { return JSON.parse(localStorage.getItem('user') || '{}') } catch { return {} } })() const productSummary = { totalQuantitySold: products?.data.reduce((sum, item) => sum + item.quantity_sold, 0), totalRevenue: products?.data.reduce((sum, item) => sum + item.revenue, 0), totalOrders: products?.data.reduce((sum, item) => sum + item.order_count, 0) } useEffect(() => { setNow(new Date()) }, []) const calculateCOGS = (totalRevenue: number, grossProfit: number) => { return totalRevenue - grossProfit } const calculateAveragePerTransaction = (totalRevenue: number, totalOrders: number) => { if (totalOrders === 0) return 0 return totalRevenue / totalOrders } const generatePDF = async () => { const reportElement = reportRef.current try { // Import jsPDF dan html2canvas const jsPDF = (await import('jspdf')).default const html2canvas = (await import('html2canvas')).default // Optimized canvas capture dengan scale lebih rendah const canvas = await html2canvas(reportElement!, { scale: 1.5, // Reduced from 2 to 1.5 useCORS: true, allowTaint: true, backgroundColor: '#ffffff', logging: false, // Disable logging for performance removeContainer: true, // Clean up after capture imageTimeout: 0, // No timeout for image loading height: reportElement!.scrollHeight, width: reportElement!.scrollWidth }) // Compress canvas using JPEG with quality setting const imgData = canvas.toDataURL('image/jpeg', 0.85) // JPEG with 85% quality instead of PNG // Create PDF with compression const pdf = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4', compress: true // Enable built-in compression }) const imgWidth = 210 const pageHeight = 295 const imgHeight = (canvas.height * imgWidth) / canvas.width let heightLeft = imgHeight let position = 0 // Add first page with compressed image pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight, '', 'FAST') // Use FAST compression heightLeft -= pageHeight // Handle multiple pages if needed while (heightLeft >= 0) { position = heightLeft - imgHeight pdf.addPage() pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight, '', 'FAST') heightLeft -= pageHeight } // Additional compression options pdf.setProperties({ title: `Laporan Transaksi Harian`, subject: 'Daily Transaction Report', author: 'Apskel POS System', creator: 'Apskel' }) // Save with optimized settings pdf.save(`laporan-transaksi-harian.pdf`, { returnPromise: true }) // Clean up canvas to free memory canvas.width = canvas.height = 0 } catch (error) { console.error('Error generating PDF:', error) alert('Terjadi kesalahan saat membuat PDF. Pastikan jsPDF dan html2canvas sudah terinstall.') } } return (
{/* Control Panel */}

Generator Laporan Transaksi Harian

Klik tombol download untuk mengeksport laporan ke PDF

{/* Report Template */}
{/* Header */}

Apskel

{outlet?.name}

{outlet?.address}

Laporan Transaksi Harian

Laporan Operasional
{/* Information Section */}
Tanggal Laporan

{formatDate(now)}

Periode Operasional

{formatDateDDMMYYYY(now)} / {formatDateDDMMYYYY(now)}

Dicetak Oleh

{user.name}

Waktu Cetak

{formatDatetime(now)}

{/* Performance Summary */}

1. Ringkasan Kinerja

Total Transaksi

{sales?.summary.total_orders}

Item Terjual

{sales?.summary.total_items}

Margin Laba Kotor

{profitLoss?.summary.gross_profit_margin.toFixed(2)}%

Pendapatan Kotor {formatCurrency(profitLoss?.summary.gross_profit ?? 0)}
Total Diskon -{formatCurrency(profitLoss?.summary.total_discount ?? 0)}
Pajak {formatCurrency(profitLoss?.summary.total_tax ?? 0)}
Pendapatan Bersih {formatCurrency(profitLoss?.summary.net_profit ?? 0)}
HPP (COGS) {formatCurrency( calculateCOGS(profitLoss?.summary.total_revenue ?? 0, profitLoss?.summary.gross_profit ?? 0) )}
Laba Kotor {formatCurrency(profitLoss?.summary.gross_profit ?? 0)}
{/* Transaction Summary */}

2. Ringkasan Transaksi

{products?.data.map((item, index) => ( ))}
Produk Kategori Qty Order Pendapatan Rata Rata
{item.product_name} {item.category_name} {item.quantity_sold} {item.order_count} {formatCurrency(item.revenue)} {formatCurrency(item.average_price)}
TOTAL {productSummary.totalQuantitySold} {productSummary.totalOrders} {formatCurrency(productSummary.totalRevenue ?? 0)}
{/* Financial Summary */}

3. Ringkasan Finansial

Pendapatan

Penjualan Kotor {formatCurrency(sales?.summary.total_sales ?? 0)}
Diskon -{formatCurrency(sales?.summary.total_discount ?? 0)}
Net Sales {formatCurrency(sales?.summary.net_sales ?? 0)}

Profitabilitas

Laba Kotor {formatCurrency(profitLoss?.summary.gross_profit ?? 0)}
Margin Laba {profitLoss?.summary.net_profit_margin.toFixed(2) ?? 0}%
HPP {formatCurrency( calculateCOGS(profitLoss?.summary.total_revenue ?? 0, profitLoss?.summary.gross_profit ?? 0) )}

Rata-rata per Transaksi

{formatCurrency( calculateAveragePerTransaction(sales?.summary.net_sales ?? 0, sales?.summary.total_orders ?? 0) )}

Item per Transaksi

{Math.round(((sales?.summary.total_items ?? 0) / (sales?.summary.total_orders ?? 0)) * 10) / 10}

Efisiensi Operasional

{Math.round(profitLoss?.summary.profitability_ratio ?? 0)}%

{/* Footer */}

© 2025 Apskel - Sistem POS Terpadu

Dicetak pada: {now.toLocaleDateString('id-ID')}

) } export default DailyPOSReport