mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE-355,356,357): Add PDF export for HPP per kandang report
This commit is contained in:
@@ -0,0 +1,490 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Page,
|
||||||
|
Text,
|
||||||
|
View,
|
||||||
|
Document,
|
||||||
|
StyleSheet,
|
||||||
|
Font,
|
||||||
|
pdf,
|
||||||
|
} from '@react-pdf/renderer';
|
||||||
|
import { HppPerKandangReport } from '@/types/api/report/hpp-per-kandang';
|
||||||
|
import { formatDate, formatNumber } from '@/lib/helper';
|
||||||
|
|
||||||
|
Font.register({
|
||||||
|
family: 'Helvetica',
|
||||||
|
src: 'helvetica',
|
||||||
|
});
|
||||||
|
|
||||||
|
const pdfStyles = StyleSheet.create({
|
||||||
|
page: {
|
||||||
|
fontSize: 10,
|
||||||
|
fontFamily: 'Helvetica',
|
||||||
|
padding: 20,
|
||||||
|
backgroundColor: '#FFFFFF',
|
||||||
|
},
|
||||||
|
titleSection: {
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
mainTitle: {
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
marginBottom: 5,
|
||||||
|
color: '#1f74bf',
|
||||||
|
},
|
||||||
|
supplierTitle: {
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
marginBottom: 8,
|
||||||
|
color: '#1f74bf',
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#000000',
|
||||||
|
marginBottom: 15,
|
||||||
|
},
|
||||||
|
tableRow: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
},
|
||||||
|
tableHeader: {
|
||||||
|
backgroundColor: '#F5F5F5',
|
||||||
|
},
|
||||||
|
tableCell: {
|
||||||
|
flex: 1,
|
||||||
|
borderRightWidth: 1,
|
||||||
|
borderRightColor: '#000000',
|
||||||
|
borderRightStyle: 'solid',
|
||||||
|
padding: 4,
|
||||||
|
fontSize: 8,
|
||||||
|
textAlign: 'left',
|
||||||
|
},
|
||||||
|
tableCellHeader: {
|
||||||
|
flex: 1,
|
||||||
|
borderRightWidth: 1,
|
||||||
|
borderRightColor: '#000000',
|
||||||
|
borderRightStyle: 'solid',
|
||||||
|
padding: 4,
|
||||||
|
fontSize: 8,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
backgroundColor: '#F5F5F5',
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: '#000000',
|
||||||
|
borderBottomStyle: 'solid',
|
||||||
|
paddingVertical: 12,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
tableCellHeaderRight: {
|
||||||
|
flex: 1,
|
||||||
|
borderRightWidth: 1,
|
||||||
|
borderRightColor: '#000000',
|
||||||
|
borderRightStyle: 'solid',
|
||||||
|
padding: 4,
|
||||||
|
fontSize: 8,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
backgroundColor: '#F5F5F5',
|
||||||
|
textAlign: 'right',
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: '#000000',
|
||||||
|
borderBottomStyle: 'solid',
|
||||||
|
paddingVertical: 12,
|
||||||
|
},
|
||||||
|
tableCellRight: {
|
||||||
|
flex: 1,
|
||||||
|
borderRightWidth: 1,
|
||||||
|
borderRightColor: '#000000',
|
||||||
|
borderRightStyle: 'solid',
|
||||||
|
padding: 4,
|
||||||
|
fontSize: 8,
|
||||||
|
textAlign: 'right',
|
||||||
|
},
|
||||||
|
tableCellCenter: {
|
||||||
|
flex: 1,
|
||||||
|
borderRightWidth: 1,
|
||||||
|
borderRightColor: '#000000',
|
||||||
|
borderRightStyle: 'solid',
|
||||||
|
padding: 4,
|
||||||
|
fontSize: 8,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
tableBorderBottom: {
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: '#000000',
|
||||||
|
borderBottomStyle: 'solid',
|
||||||
|
},
|
||||||
|
supplierSection: {
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
supplierSectionBreak: {
|
||||||
|
marginBottom: 15,
|
||||||
|
},
|
||||||
|
parameterBadge: {
|
||||||
|
backgroundColor: '#F5F5F5',
|
||||||
|
color: '#333333',
|
||||||
|
padding: 4,
|
||||||
|
borderRadius: 4,
|
||||||
|
fontSize: 8,
|
||||||
|
marginRight: 8,
|
||||||
|
marginBottom: 4,
|
||||||
|
},
|
||||||
|
parameterContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
interface HppPerKandangExportParams {
|
||||||
|
data: HppPerKandangReport;
|
||||||
|
params: {
|
||||||
|
area_name?: string;
|
||||||
|
location_name?: string;
|
||||||
|
kandang_name?: string;
|
||||||
|
period?: string;
|
||||||
|
weight_min?: string;
|
||||||
|
weight_max?: string;
|
||||||
|
show_unrecorded?: string;
|
||||||
|
sort_by?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WeightRangeGroup {
|
||||||
|
weight_min: number;
|
||||||
|
weight_max: number;
|
||||||
|
items: HppPerKandangReport['rows'];
|
||||||
|
totals: {
|
||||||
|
total_remaining_chicken_birds: number;
|
||||||
|
total_remaining_chicken_weight_kg: number;
|
||||||
|
average_weight_kg: number;
|
||||||
|
total_hpp_rp: number;
|
||||||
|
total_remaining_value_rp: number;
|
||||||
|
all_feed_suppliers: string[];
|
||||||
|
all_doc_suppliers: string[];
|
||||||
|
average_doc_price_rp: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupDataByWeightRange = (
|
||||||
|
data: HppPerKandangReport['rows']
|
||||||
|
): WeightRangeGroup[] => {
|
||||||
|
const groups: {
|
||||||
|
[key: string]: WeightRangeGroup;
|
||||||
|
} = {};
|
||||||
|
|
||||||
|
data.forEach((item) => {
|
||||||
|
const key = `${item.weight_range.weight_min}-${item.weight_range.weight_max}`;
|
||||||
|
if (!groups[key]) {
|
||||||
|
groups[key] = {
|
||||||
|
weight_min: item.weight_range.weight_min,
|
||||||
|
weight_max: item.weight_range.weight_max,
|
||||||
|
items: [],
|
||||||
|
totals: {
|
||||||
|
total_remaining_chicken_birds: 0,
|
||||||
|
total_remaining_chicken_weight_kg: 0,
|
||||||
|
average_weight_kg: 0,
|
||||||
|
total_hpp_rp: 0,
|
||||||
|
total_remaining_value_rp: 0,
|
||||||
|
all_feed_suppliers: [],
|
||||||
|
all_doc_suppliers: [],
|
||||||
|
average_doc_price_rp: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
groups[key].items.push(item);
|
||||||
|
|
||||||
|
groups[key].totals.total_remaining_chicken_birds +=
|
||||||
|
item.remaining_chicken_birds;
|
||||||
|
groups[key].totals.total_remaining_chicken_weight_kg +=
|
||||||
|
item.remaining_chicken_weight_kg;
|
||||||
|
groups[key].totals.total_hpp_rp += item.hpp_rp;
|
||||||
|
groups[key].totals.total_remaining_value_rp += item.remaining_value_rp;
|
||||||
|
|
||||||
|
item.feed_suppliers?.forEach((supplier) => {
|
||||||
|
const alias = supplier.alias || supplier.name;
|
||||||
|
if (!groups[key].totals.all_feed_suppliers.includes(alias)) {
|
||||||
|
groups[key].totals.all_feed_suppliers.push(alias);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
item.doc_suppliers?.forEach((supplier) => {
|
||||||
|
const alias = supplier.alias || supplier.name;
|
||||||
|
if (!groups[key].totals.all_doc_suppliers.includes(alias)) {
|
||||||
|
groups[key].totals.all_doc_suppliers.push(alias);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.values(groups).forEach((group) => {
|
||||||
|
group.totals.average_weight_kg =
|
||||||
|
group.totals.total_remaining_chicken_weight_kg /
|
||||||
|
group.totals.total_remaining_chicken_birds;
|
||||||
|
group.totals.average_doc_price_rp =
|
||||||
|
group.items.reduce((sum, item) => sum + item.average_doc_price_rp, 0) /
|
||||||
|
group.items.length;
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.values(groups).sort((a, b) => a.weight_min - b.weight_min);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getParameterText = (params: HppPerKandangExportParams['params']) => {
|
||||||
|
const paramsText = [];
|
||||||
|
|
||||||
|
if (params.period) {
|
||||||
|
const formattedDate = formatDate(params.period, 'DD MMM YYYY');
|
||||||
|
paramsText.push(`Tanggal: ${formattedDate}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentDate = formatDate(new Date().toISOString(), 'DD MMM YYYY HH:mm');
|
||||||
|
paramsText.push(`Dicetak: ${currentDate}`);
|
||||||
|
|
||||||
|
return paramsText;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createPDFDocument = (
|
||||||
|
data: HppPerKandangExportParams['data'],
|
||||||
|
params: HppPerKandangExportParams['params']
|
||||||
|
) => {
|
||||||
|
const groupedByWeightRange = groupDataByWeightRange(data.rows);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Document>
|
||||||
|
<Page size='A3' orientation='landscape' style={pdfStyles.page}>
|
||||||
|
{/* Title and Parameters */}
|
||||||
|
<View style={pdfStyles.titleSection}>
|
||||||
|
<Text style={pdfStyles.mainTitle}>
|
||||||
|
Laporan > HPP Harian Kandang
|
||||||
|
</Text>
|
||||||
|
<View style={pdfStyles.parameterContainer}>
|
||||||
|
{getParameterText(params).map((param, index) => (
|
||||||
|
<View key={index} style={pdfStyles.parameterBadge}>
|
||||||
|
<Text>{param}</Text>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Rekapitulasi Section */}
|
||||||
|
<View style={pdfStyles.supplierSection}>
|
||||||
|
<Text style={pdfStyles.supplierTitle}>Rekapitulasi</Text>
|
||||||
|
|
||||||
|
<View style={pdfStyles.table}>
|
||||||
|
{/* Table Header */}
|
||||||
|
<View style={[pdfStyles.tableRow, pdfStyles.tableHeader]}>
|
||||||
|
<View style={[pdfStyles.tableCellHeader, { flex: 1.2 }]}>
|
||||||
|
<Text>Rentang BW</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1 }]}>
|
||||||
|
<Text>Sisa Ekor</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1 }]}>
|
||||||
|
<Text>Sisa Kg</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.2 }]}>
|
||||||
|
<Text>Rata-Rata Bobot (Kg)</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeader, { flex: 1.5 }]}>
|
||||||
|
<Text>Feed (Supplier)</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeader, { flex: 1.2 }]}>
|
||||||
|
<Text>DOC (Supplier)</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.2 }]}>
|
||||||
|
<Text>Rata-Rata Harga DOC</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1 }]}>
|
||||||
|
<Text>HPP</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.2 }]}>
|
||||||
|
<Text>Nominal Sisa</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Table Body - Rekapitulasi */}
|
||||||
|
{groupedByWeightRange.map((group, index) => (
|
||||||
|
<View
|
||||||
|
key={index}
|
||||||
|
style={[
|
||||||
|
pdfStyles.tableRow,
|
||||||
|
index < groupedByWeightRange.length - 1
|
||||||
|
? pdfStyles.tableBorderBottom
|
||||||
|
: {},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<View style={[pdfStyles.tableCellCenter, { flex: 1.2 }]}>
|
||||||
|
<Text>
|
||||||
|
{group.weight_min.toFixed(2)} -{' '}
|
||||||
|
{group.weight_max.toFixed(2)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
||||||
|
<Text>
|
||||||
|
{formatNumber(group.totals.total_remaining_chicken_birds)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
||||||
|
<Text>
|
||||||
|
{formatNumber(
|
||||||
|
group.totals.total_remaining_chicken_weight_kg
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
|
<Text>{formatNumber(group.totals.average_weight_kg)}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}>
|
||||||
|
<Text>{group.totals.all_feed_suppliers.join(' | ')}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCell, { flex: 1.2 }]}>
|
||||||
|
<Text>{group.totals.all_doc_suppliers.join(' | ')}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
|
<Text>{formatNumber(group.totals.average_doc_price_rp)}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
||||||
|
<Text>
|
||||||
|
{
|
||||||
|
(group.totals.total_remaining_chicken_birds > 0
|
||||||
|
? group.totals.total_hpp_rp /
|
||||||
|
group.totals.total_remaining_chicken_birds
|
||||||
|
: 0,
|
||||||
|
2)
|
||||||
|
}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
|
<Text>
|
||||||
|
{formatNumber(group.totals.total_remaining_value_rp)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Detail Per Kandang Section */}
|
||||||
|
<View style={pdfStyles.supplierSectionBreak}>
|
||||||
|
<Text style={pdfStyles.supplierTitle}>Detail Per Kandang</Text>
|
||||||
|
|
||||||
|
<View style={pdfStyles.table}>
|
||||||
|
{/* Table Header */}
|
||||||
|
<View style={[pdfStyles.tableRow, pdfStyles.tableHeader]}>
|
||||||
|
<View style={[pdfStyles.tableCellHeader, { flex: 0.5 }]}>
|
||||||
|
<Text>No</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeader, { flex: 1.5 }]}>
|
||||||
|
<Text>Kandang</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeader, { flex: 1 }]}>
|
||||||
|
<Text>Rentang BW</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 0.8 }]}>
|
||||||
|
<Text>Sisa Ekor</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 0.8 }]}>
|
||||||
|
<Text>Sisa Kg</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1 }]}>
|
||||||
|
<Text>Rata-Rata Bobot (Kg)</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeader, { flex: 1.2 }]}>
|
||||||
|
<Text>Feed (Supplier)</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeader, { flex: 1 }]}>
|
||||||
|
<Text>DOC (Supplier)</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.2 }]}>
|
||||||
|
<Text>Rata-Rata Harga DOC</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 0.8 }]}>
|
||||||
|
<Text>HPP</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.2 }]}>
|
||||||
|
<Text>Nominal Sisa</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Table Body - Detail Per Kandang */}
|
||||||
|
{data.rows.map((item, index) => (
|
||||||
|
<View
|
||||||
|
key={index}
|
||||||
|
style={[
|
||||||
|
pdfStyles.tableRow,
|
||||||
|
index < data.rows.length - 1
|
||||||
|
? pdfStyles.tableBorderBottom
|
||||||
|
: {},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<View style={[pdfStyles.tableCellCenter, { flex: 0.5 }]}>
|
||||||
|
<Text>{index + 1}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}>
|
||||||
|
<Text>{item.kandang?.name || '-'}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
||||||
|
<Text>
|
||||||
|
{item.weight_range.weight_min.toFixed(2)} -{' '}
|
||||||
|
{item.weight_range.weight_max.toFixed(2)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellRight, { flex: 0.8 }]}>
|
||||||
|
<Text>{formatNumber(item.remaining_chicken_birds)}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellRight, { flex: 0.8 }]}>
|
||||||
|
<Text>{formatNumber(item.remaining_chicken_weight_kg)}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
||||||
|
<Text>{formatNumber(item.avg_weight_kg)}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCell, { flex: 1.2 }]}>
|
||||||
|
<Text>
|
||||||
|
{item.feed_suppliers
|
||||||
|
?.map((s) => s.alias || s.name)
|
||||||
|
.join(' | ')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
||||||
|
<Text>
|
||||||
|
{item.doc_suppliers
|
||||||
|
?.map((s) => s.alias || s.name)
|
||||||
|
.join(' | ')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
|
<Text>{formatNumber(item.average_doc_price_rp)}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellRight, { flex: 0.8 }]}>
|
||||||
|
<Text>{formatNumber(item.hpp_rp)}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
|
<Text>{formatNumber(item.remaining_value_rp)}</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</Page>
|
||||||
|
</Document>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const generateHppPerKandangPDF = async (
|
||||||
|
data: HppPerKandangExportParams['data'],
|
||||||
|
params: HppPerKandangExportParams['params']
|
||||||
|
): Promise<void> => {
|
||||||
|
const PDFDocument = createPDFDocument(data, params);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const blob = await pdf(PDFDocument).toBlob();
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = `laporan-hpp-harian-kandang-${formatDate(new Date(), 'YYYY-MM-DD-HHmm')}.pdf`;
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -23,6 +23,7 @@ import Button from '@/components/Button';
|
|||||||
import Dropdown from '@/components/dropdown/Dropdown';
|
import Dropdown from '@/components/dropdown/Dropdown';
|
||||||
import MenuItem from '@/components/menu/MenuItem';
|
import MenuItem from '@/components/menu/MenuItem';
|
||||||
import Menu from '@/components/menu/Menu';
|
import Menu from '@/components/menu/Menu';
|
||||||
|
import { generateHppPerKandangPDF } from '../export/HppPerkandangExport';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import * as XLSX from 'xlsx';
|
import * as XLSX from 'xlsx';
|
||||||
|
|
||||||
@@ -380,6 +381,54 @@ const HppPerKandangTab = () => {
|
|||||||
kandangOptions,
|
kandangOptions,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const handleExportPDF = useCallback(async () => {
|
||||||
|
if (!hppPerKandang || !isResponseSuccess(hppPerKandang)) {
|
||||||
|
toast.error('Tidak ada data untuk diekspor.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const areaName = tableFilterState.area_id
|
||||||
|
? areaOptions.find(
|
||||||
|
(opt) => opt.value === Number(tableFilterState.area_id)
|
||||||
|
)?.label || 'Semua Area'
|
||||||
|
: 'Semua Area';
|
||||||
|
|
||||||
|
const locationName = tableFilterState.location_id
|
||||||
|
? locationOptions.find(
|
||||||
|
(opt) => opt.value === Number(tableFilterState.location_id)
|
||||||
|
)?.label || 'Semua Lokasi'
|
||||||
|
: 'Semua Lokasi';
|
||||||
|
|
||||||
|
const kandangName = tableFilterState.kandang_id
|
||||||
|
? kandangOptions.find(
|
||||||
|
(opt) => opt.value === Number(tableFilterState.kandang_id)
|
||||||
|
)?.label || 'Semua Kandang'
|
||||||
|
: 'Semua Kandang';
|
||||||
|
|
||||||
|
await generateHppPerKandangPDF(hppPerKandang.data, {
|
||||||
|
area_name: areaName,
|
||||||
|
location_name: locationName,
|
||||||
|
kandang_name: kandangName,
|
||||||
|
period: tableFilterState.period,
|
||||||
|
weight_min: tableFilterState.weight_min,
|
||||||
|
weight_max: tableFilterState.weight_max,
|
||||||
|
show_unrecorded: tableFilterState.show_unrecorded.toString(),
|
||||||
|
sort_by: tableFilterState.sort_by,
|
||||||
|
});
|
||||||
|
|
||||||
|
toast.success('PDF berhasil dibuat dan diunduh.');
|
||||||
|
} catch {
|
||||||
|
toast.error('Gagal membuat PDF. Silakan coba lagi.');
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
hppPerKandang,
|
||||||
|
tableFilterState,
|
||||||
|
areaOptions,
|
||||||
|
locationOptions,
|
||||||
|
kandangOptions,
|
||||||
|
]);
|
||||||
|
|
||||||
// ===== TABLE COLUMNS DEFINITION =====
|
// ===== TABLE COLUMNS DEFINITION =====
|
||||||
const totals: Totals = useMemo(() => {
|
const totals: Totals = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
@@ -592,12 +641,7 @@ const HppPerKandangTab = () => {
|
|||||||
>
|
>
|
||||||
<Menu className='w-32'>
|
<Menu className='w-32'>
|
||||||
<MenuItem title='Excel' onClick={handleExportExcel} />
|
<MenuItem title='Excel' onClick={handleExportExcel} />
|
||||||
<MenuItem
|
<MenuItem title='PDF' onClick={handleExportPDF} />
|
||||||
title='PDF'
|
|
||||||
onClick={() => {
|
|
||||||
alert('Fitur belum tersedia');
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Menu>
|
</Menu>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user