Files
lti-web-client/src/components/pages/report/DailyMarketingReportPDF.tsx
T

551 lines
16 KiB
TypeScript

'use client';
import {
Document,
Image,
Page,
StyleSheet,
Text,
View,
} from '@react-pdf/renderer';
import { DailyMarketingReport } from '@/types/api/report/marketing';
import { formatCurrency, formatDate, formatNumber } from '@/lib/helper';
interface DailyMarketingReportPDFProps {
data?: DailyMarketingReport;
}
const DailyMarketingReportPDFStyle = StyleSheet.create({
page: {
paddingTop: 24,
paddingBottom: 64,
paddingHorizontal: 16, // Reduce padding to fit more columns
orientation: 'landscape',
},
companyInfoHeader: {
width: '100%',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'flex-start',
marginBottom: 8,
},
companyLogo: {
width: 64,
height: 'auto',
},
companyInfoHeaderDate: {
paddingTop: 8,
fontSize: 10,
},
companyName: {
fontSize: 12,
fontWeight: 'bold',
marginBottom: 4,
},
companyAddress: {
fontSize: 8,
maxWidth: 400,
marginBottom: 10,
},
title: {
marginTop: 16,
fontSize: 14,
lineHeight: '150%',
textAlign: 'center',
fontFamily: 'Times-Roman',
fontWeight: 'bold',
},
footer: {
width: '100%',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingHorizontal: 16,
position: 'absolute',
fontSize: 8,
bottom: 30,
left: 0,
right: 0,
textAlign: 'center',
color: 'grey',
},
// Table Styles
table: {
width: '100%',
marginTop: 16,
borderWidth: 1,
borderColor: '#000000',
borderBottomWidth: 0,
fontSize: 7, // Smaller font for report
},
tableRow: {
flexDirection: 'row',
borderBottomWidth: 1,
borderBottomColor: '#000000',
alignItems: 'center',
minHeight: 20,
},
tableHeader: {
backgroundColor: '#f0f0f0',
fontWeight: 'bold',
},
// Columns definition (Total 100%)
colNo: {
width: '3%',
padding: 2,
textAlign: 'center',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colSoDate: {
width: '6%',
padding: 2,
textAlign: 'left',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colDoDate: {
width: '6%',
padding: 2,
textAlign: 'left',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colAging: {
width: '3%',
padding: 2,
textAlign: 'center',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colWarehouse: {
width: '7%',
padding: 2,
textAlign: 'left',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colCustomer: {
width: '9%',
padding: 2,
textAlign: 'left',
borderRightWidth: 1,
borderRightColor: '#000000',
}, // Reduced slightly
colSales: {
width: '6%',
padding: 2,
textAlign: 'left',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colProduct: {
width: '8%',
padding: 2,
textAlign: 'left',
borderRightWidth: 1,
borderRightColor: '#000000',
}, // Reduced slightly
colDoNumber: {
width: '7%',
padding: 2,
textAlign: 'left',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colVehicle: {
width: '5%',
padding: 2,
textAlign: 'left',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colMarketingType: {
width: '5%',
padding: 2,
textAlign: 'left',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colQty: {
width: '4%',
padding: 2,
textAlign: 'right',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colAvgWeight: {
width: '4%',
padding: 2,
textAlign: 'right',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colTotalWeight: {
width: '5%',
padding: 2,
textAlign: 'right',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colSalesPrice: {
width: '5%',
padding: 2,
textAlign: 'right',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colHppPrice: {
width: '5%',
padding: 2,
textAlign: 'right',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colSalesAmount: {
width: '6%',
padding: 2,
textAlign: 'right',
borderRightWidth: 1,
borderRightColor: '#000000',
},
colHppAmount: { width: '6%', padding: 2, textAlign: 'right' }, // Last column
// Text inside columns
cellText: {
fontSize: 6,
},
headerText: {
fontSize: 7,
fontWeight: 'bold',
textAlign: 'center',
},
// Utils
doubleDivider: {
width: '100%',
height: 6,
borderTop: '2px solid black',
borderBottom: '2px solid black',
},
// Summary
summaryContainer: {
marginTop: 12,
flexDirection: 'row',
justifyContent: 'flex-end',
width: '100%',
},
summaryTable: {
width: '30%',
borderWidth: 1,
borderColor: '#000000',
fontSize: 8,
},
summaryRow: {
flexDirection: 'row',
padding: 2,
borderBottomWidth: 1,
borderBottomColor: '#eee',
},
summaryLabel: {
width: '50%',
fontWeight: 'bold',
},
summaryValue: {
width: '50%',
textAlign: 'right',
},
});
const DailyMarketingReportPDF = ({ data }: DailyMarketingReportPDFProps) => {
const rows = data?.rows || [];
const summary = data?.summary;
return (
<Document>
<Page
style={DailyMarketingReportPDFStyle.page}
orientation='landscape'
size='A4'
>
<View>
<View style={DailyMarketingReportPDFStyle.companyInfoHeader}>
<Image
style={DailyMarketingReportPDFStyle.companyLogo}
src='/assets/img/lti-logo.png'
/>
<Text style={DailyMarketingReportPDFStyle.companyInfoHeaderDate}>
{formatDate(Date.now(), 'DD MMMM YYYY')}
</Text>
</View>
<View>
<Text style={DailyMarketingReportPDFStyle.companyName}>
PT LUMBUNG TELUR INDONESIA
</Text>
<Text style={DailyMarketingReportPDFStyle.companyAddress}>
SOHO Building Lt.3 (Paris Van Java), Jalan Karang Tinggal, Kel.
Cipedes, Kec. Sukajadi, Kota Bandung 40162
</Text>
<View style={DailyMarketingReportPDFStyle.doubleDivider} />
</View>
</View>
<Text style={DailyMarketingReportPDFStyle.title}>
Laporan Penjualan Harian
</Text>
{/* Data Table */}
<View style={DailyMarketingReportPDFStyle.table}>
{/* Header */}
<View
style={[
DailyMarketingReportPDFStyle.tableRow,
DailyMarketingReportPDFStyle.tableHeader,
]}
>
<View style={DailyMarketingReportPDFStyle.colNo}>
<Text style={DailyMarketingReportPDFStyle.headerText}>No</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colSoDate}>
<Text style={DailyMarketingReportPDFStyle.headerText}>
Tgl SO
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colDoDate}>
<Text style={DailyMarketingReportPDFStyle.headerText}>
Tgl DO
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colAging}>
<Text style={DailyMarketingReportPDFStyle.headerText}>Aging</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colWarehouse}>
<Text style={DailyMarketingReportPDFStyle.headerText}>
Gudang
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colCustomer}>
<Text style={DailyMarketingReportPDFStyle.headerText}>
Pelanggan
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colSales}>
<Text style={DailyMarketingReportPDFStyle.headerText}>Sales</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colProduct}>
<Text style={DailyMarketingReportPDFStyle.headerText}>
Produk
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colDoNumber}>
<Text style={DailyMarketingReportPDFStyle.headerText}>No DO</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colVehicle}>
<Text style={DailyMarketingReportPDFStyle.headerText}>
Plat No
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colMarketingType}>
<Text style={DailyMarketingReportPDFStyle.headerText}>Tipe</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colQty}>
<Text style={DailyMarketingReportPDFStyle.headerText}>Qty</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colAvgWeight}>
<Text style={DailyMarketingReportPDFStyle.headerText}>
Rerata
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colTotalWeight}>
<Text style={DailyMarketingReportPDFStyle.headerText}>Berat</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colSalesPrice}>
<Text style={DailyMarketingReportPDFStyle.headerText}>
Hrg Jual
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colHppPrice}>
<Text style={DailyMarketingReportPDFStyle.headerText}>
HPP/kg
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colSalesAmount}>
<Text style={DailyMarketingReportPDFStyle.headerText}>
Total Jual
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colHppAmount}>
<Text style={DailyMarketingReportPDFStyle.headerText}>
Total HPP
</Text>
</View>
</View>
{/* Rows */}
{rows.map((row, index) => (
<View style={DailyMarketingReportPDFStyle.tableRow} key={index}>
<View style={DailyMarketingReportPDFStyle.colNo}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{index + 1}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colSoDate}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{formatDate(row.so_date, 'DD/MM/YYYY')}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colDoDate}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{formatDate(row.do_date, 'DD/MM/YYYY')}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colAging}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{row.aging_days}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colWarehouse}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{row.warehouse?.name}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colCustomer}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{row.customer?.name}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colSales}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{row.sales}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colProduct}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{row.product?.name}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colDoNumber}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{row.do_number}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colVehicle}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{row.vehicle_number}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colMarketingType}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{row.marketing_type}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colQty}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{formatNumber(row.qty)}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colAvgWeight}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{formatNumber(row.average_weight_kg)}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colTotalWeight}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{formatNumber(row.total_weight_kg)}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colSalesPrice}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{formatCurrency(row.sales_price_per_kg)}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colHppPrice}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{formatCurrency(row.hpp_price_per_kg)}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colSalesAmount}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{formatCurrency(row.sales_amount)}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.colHppAmount}>
<Text style={DailyMarketingReportPDFStyle.cellText}>
{formatCurrency(row.hpp_amount)}
</Text>
</View>
</View>
))}
</View>
{/* Summary */}
<View style={DailyMarketingReportPDFStyle.summaryContainer}>
<View style={DailyMarketingReportPDFStyle.summaryTable}>
<View style={DailyMarketingReportPDFStyle.summaryRow}>
<Text style={DailyMarketingReportPDFStyle.summaryLabel}>
Total Qty:
</Text>
<Text style={DailyMarketingReportPDFStyle.summaryValue}>
{formatNumber(summary?.total_qty ?? 0)}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.summaryRow}>
<Text style={DailyMarketingReportPDFStyle.summaryLabel}>
Total Berat (kg):
</Text>
<Text style={DailyMarketingReportPDFStyle.summaryValue}>
{formatNumber(summary?.total_weight_kg ?? 0)}
</Text>
</View>
<View style={DailyMarketingReportPDFStyle.summaryRow}>
<Text style={DailyMarketingReportPDFStyle.summaryLabel}>
Total Penjualan:
</Text>
<Text style={DailyMarketingReportPDFStyle.summaryValue}>
{formatCurrency(summary?.total_sales_amount ?? 0)}
</Text>
</View>
<View
style={[
DailyMarketingReportPDFStyle.summaryRow,
{ borderBottomWidth: 0 },
]}
>
<Text style={DailyMarketingReportPDFStyle.summaryLabel}>
Total HPP:
</Text>
<Text style={DailyMarketingReportPDFStyle.summaryValue}>
{formatCurrency(summary?.total_hpp_amount ?? 0)}
</Text>
</View>
</View>
</View>
<View style={DailyMarketingReportPDFStyle.footer} fixed>
<Text
render={({ pageNumber, totalPages }) =>
`${pageNumber} / ${totalPages}`
}
fixed
/>
</View>
</Page>
</Document>
);
};
export default DailyMarketingReportPDF;