From 606380460e75cb0b5493fbf3d1bc746e49ab54b3 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Mon, 9 Feb 2026 15:58:28 +0700 Subject: [PATCH 1/6] feat(FE): Add PDF helper components for badges and typography --- .../helper/pdf/badge/PdfParamBadge.tsx | 25 ++++++ .../helper/pdf/badge/PdfStatusBadge.tsx | 47 +++++++++++ .../helper/pdf/typography/PdfTypography.tsx | 83 +++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 src/components/helper/pdf/badge/PdfParamBadge.tsx create mode 100644 src/components/helper/pdf/badge/PdfStatusBadge.tsx create mode 100644 src/components/helper/pdf/typography/PdfTypography.tsx diff --git a/src/components/helper/pdf/badge/PdfParamBadge.tsx b/src/components/helper/pdf/badge/PdfParamBadge.tsx new file mode 100644 index 00000000..01fc1a63 --- /dev/null +++ b/src/components/helper/pdf/badge/PdfParamBadge.tsx @@ -0,0 +1,25 @@ +import { Text, View, StyleSheet } from '@react-pdf/renderer'; + +type PdfParamBadgeProps = { + children: React.ReactNode; +}; + +const styles = StyleSheet.create({ + parameterBadge: { + backgroundColor: '#F5F5F5', + color: '#333333', + padding: 4, + borderRadius: 4, + fontSize: 8, + marginRight: 8, + marginBottom: 4, + }, +}); + +export const PdfParamBadge = ({ children }: PdfParamBadgeProps) => { + return ( + + {children} + + ); +}; diff --git a/src/components/helper/pdf/badge/PdfStatusBadge.tsx b/src/components/helper/pdf/badge/PdfStatusBadge.tsx new file mode 100644 index 00000000..e0444284 --- /dev/null +++ b/src/components/helper/pdf/badge/PdfStatusBadge.tsx @@ -0,0 +1,47 @@ +import { Text, View, StyleSheet } from '@react-pdf/renderer'; + +type PdfStatusBadgeProps = { + children: React.ReactNode; + backgroundColor?: string; + textColor?: string; + borderColor?: string; +}; + +const styles = StyleSheet.create({ + statusBadge: { + paddingVertical: 2, + paddingHorizontal: 4, + borderRadius: 12, + fontSize: 7, + fontWeight: 'bold', + borderWidth: 1, + borderStyle: 'solid', + }, + statusBadgeText: { + fontSize: 7, + fontWeight: 'bold', + }, +}); + +export const PdfStatusBadge = ({ + children, + backgroundColor = '#F5F5F5', + textColor = '#333333', + borderColor = '#E5E7EB', +}: PdfStatusBadgeProps) => { + return ( + + + {children} + + + ); +}; diff --git a/src/components/helper/pdf/typography/PdfTypography.tsx b/src/components/helper/pdf/typography/PdfTypography.tsx new file mode 100644 index 00000000..31efe449 --- /dev/null +++ b/src/components/helper/pdf/typography/PdfTypography.tsx @@ -0,0 +1,83 @@ +import { Color } from '@/types/theme'; +import { Text, StyleSheet } from '@react-pdf/renderer'; + +type TypographySize = 'h1' | 'h2' | 'h3' | 'h4' | 'p' | 'small' | 'label'; + +type TypographyVariant = Color | 'default'; + +type PdfTypographyProps = { + children: React.ReactNode; + size?: TypographySize; + variant?: TypographyVariant; + color?: string; + marginBottom?: number; +}; + +const styles = StyleSheet.create({ + h1: { + fontSize: 14, + fontWeight: 'bold', + marginBottom: 5, + }, + h2: { + fontSize: 12, + fontWeight: 'bold', + marginBottom: 8, + }, + h3: { + fontSize: 10, + fontWeight: 'bold', + marginBottom: 4, + }, + h4: { + fontSize: 9, + fontWeight: 'bold', + marginBottom: 3, + }, + p: { + fontSize: 10, + marginBottom: 4, + }, + small: { + fontSize: 8, + marginBottom: 2, + }, + label: { + fontSize: 9, + marginBottom: 5, + }, +}); + +const variantColors: Record = { + default: '#333333', + primary: '#1f74bf', + secondary: '#6B7280', + accent: '#8B5CF6', + neutral: '#6B7280', + info: '#3B82F6', + success: '#065F46', + warning: '#92400E', + error: '#DC2626', + none: '#333333', +}; + +export const PdfTypography = ({ + children, + size = 'p', + variant = 'default', + color, + marginBottom, +}: PdfTypographyProps) => { + const sizeStyle = styles[size]; + const textColor = color || variantColors[variant]; + + const customStyle = { + ...(marginBottom !== undefined && { marginBottom }), + }; + + return ( + + {children} + + ); +}; From c86f0379b5da38b4c7e283ad8a7f8492db8f3301 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Mon, 9 Feb 2026 16:01:12 +0700 Subject: [PATCH 2/6] refactor(FE): Refactor CustomerPaymentExportPDF to use reusable PDF components --- .../export/CustomerPaymentExportPDF.tsx | 156 ++++-------------- 1 file changed, 36 insertions(+), 120 deletions(-) diff --git a/src/components/pages/report/finance/export/CustomerPaymentExportPDF.tsx b/src/components/pages/report/finance/export/CustomerPaymentExportPDF.tsx index d132be9a..61e8792a 100644 --- a/src/components/pages/report/finance/export/CustomerPaymentExportPDF.tsx +++ b/src/components/pages/report/finance/export/CustomerPaymentExportPDF.tsx @@ -2,7 +2,6 @@ import { Page, - Text, View, Document, StyleSheet, @@ -18,6 +17,9 @@ import { PdfTbodyCell, PdfTfootCell, } from '@/components/helper/pdf/table'; +import { PdfParamBadge } from '@/components/helper/pdf/badge/PdfParamBadge'; +import { PdfStatusBadge } from '@/components/helper/pdf/badge/PdfStatusBadge'; +import { PdfTypography } from '@/components/helper/pdf/typography/PdfTypography'; Font.register({ family: 'Helvetica', @@ -34,53 +36,6 @@ const pdfStyles = StyleSheet.create({ titleSection: { marginBottom: 10, }, - mainTitle: { - fontSize: 14, - fontWeight: 'bold', - marginBottom: 5, - color: '#1f74bf', - }, - supplierTitle: { - fontSize: 12, - fontWeight: 'bold', - marginBottom: 8, - color: '#1f74bf', - }, - supplierInfo: { - fontSize: 9, - marginBottom: 5, - color: '#333333', - }, - badge: { - backgroundColor: '#1f74bf', - color: '#FFFFFF', - padding: 2, - borderRadius: 2, - fontSize: 7, - fontWeight: 'bold', - alignSelf: 'center', - marginRight: 4, - }, - badgeLunas: { - backgroundColor: '#1f74bf', - color: '#FFFFFF', - }, - badgeBelumLunas: { - backgroundColor: '#F97316', - color: '#FFFFFF', - }, - textError: { - color: '#DC2626', - }, - parameterBadge: { - backgroundColor: '#F5F5F5', - color: '#333333', - padding: 4, - borderRadius: 4, - fontSize: 8, - marginRight: 8, - marginBottom: 4, - }, parameterContainer: { flexDirection: 'row', flexWrap: 'wrap', @@ -100,38 +55,6 @@ interface CustomerPaymentExportPDFParams { }; } -const getParameterText = ( - params?: CustomerPaymentExportPDFParams['params'] -) => { - const paramsText = []; - - if (params?.customer_name) { - paramsText.push(`Customer: ${params.customer_name}`); - } else { - paramsText.push('Semua Customer'); - } - - // TODO: Uncomment when BE is ready - // if (params?.sales) { - // paramsText.push(`Sales: ${params.sales}`); - // } - - if (params?.start_date && params?.end_date) { - const startDate = formatDate(params.start_date, 'DD MMM YYYY'); - const endDate = formatDate(params.end_date, 'DD MMM YYYY'); - paramsText.push(`Periode: ${startDate} - ${endDate}`); - } else if (params?.start_date) { - const startDate = formatDate(params.start_date, 'DD MMM YYYY'); - paramsText.push(`Tanggal: ${startDate}`); - } - - const currentDate = formatDate(new Date(), 'DD MMM YYYY HH:mm'); - paramsText.push(`Dicetak: ${currentDate}`); - - return paramsText; -}; - -// Helper functions for PdfTable const getTableColumns = (): PdfColumn[] => [ { key: 'no', header: 'No', flex: 0.5, align: 'center' }, { key: 'trans_date', header: 'Tanggal DO', flex: 1.2, align: 'center' }, @@ -221,15 +144,14 @@ const getTableData = ( { key: 'status', value: item.status ? ( - - {item.status === 'LUNAS' ? 'Lunas' : 'Belum Lunas'} + + + {item.status === 'LUNAS' ? 'Lunas' : 'Belum Lunas'} + ) : ( '-' @@ -302,43 +224,37 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => { > {/* Title and Parameters */} - + Laporan > Kontrol Pembayaran Customer - + - - - Periode:{' '} - {params.params?.start_date - ? formatDate(params.params.start_date, 'DD MMM YYYY') - : '-'}{' '} - s.d{' '} - {params.params?.end_date - ? formatDate(params.params.end_date, 'DD MMM YYYY') - : '-'} - - + + Periode:{' '} + {params.params?.start_date + ? formatDate(params.params.start_date, 'DD MMM YYYY') + : '-'}{' '} + s.d{' '} + {params.params?.end_date + ? formatDate(params.params.end_date, 'DD MMM YYYY') + : '-'} + {/* TODO: Uncomment when BE is ready */} - {/* - Filter Tanggal: Tanggal DO - */} - - - Customer: {params.params?.customer_name || 'Semua Customer'} - - - - - Dicetak: {formatDate(new Date(), 'DD MMM YYYY HH:mm')} - - + {/* + Filter Tanggal: Tanggal DO + */} + + Customer: {params.params?.customer_name || 'Semua Customer'} + + + Dicetak: {formatDate(new Date(), 'DD MMM YYYY HH:mm')} + - + {customerReport.customer.name} - - + + Alamat: {customerReport.customer.address || '-'} - + {/* Table */} From 4cf2f77265c58c2aecbe292911992f3e3331188f Mon Sep 17 00:00:00 2001 From: rstubryan Date: Mon, 9 Feb 2026 17:01:28 +0700 Subject: [PATCH 3/6] fix(FE): Fix marketing type value logic in SalesOrderFormModal --- src/components/pages/marketing/SalesOrderFormModal.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/pages/marketing/SalesOrderFormModal.tsx b/src/components/pages/marketing/SalesOrderFormModal.tsx index 3d62c516..5c4d6bb2 100644 --- a/src/components/pages/marketing/SalesOrderFormModal.tsx +++ b/src/components/pages/marketing/SalesOrderFormModal.tsx @@ -198,6 +198,13 @@ const SalesOrderFormModal = ({ : 'KG' // termasuk "QTY" dan "KG" : undefined; + // Jika value dari data product ada week, kirim "AYAM_PULLET, jika tidak ada kirim "AYAM" + let marketingTypeValue = + product.marketing_type?.value?.toUpperCase() || ''; + if (marketingTypeValue === 'AYAM,AYAM_PULLET') { + marketingTypeValue = product.week ? 'AYAM_PULLET' : 'AYAM'; + } + return { vehicle_number: product.vehicle_number as string, kandang_id: product.kandang_id as number, @@ -207,8 +214,7 @@ const SalesOrderFormModal = ({ qty: parseFloat(String(product.qty || 0)), avg_weight: parseFloat(String(product.avg_weight || 0)), total_price: parseFloat(String(product.total_price || 0)), - marketing_type: - product.marketing_type?.value?.toUpperCase() || '', + marketing_type: marketingTypeValue, convertion_unit: normalizedConvertionUnit, weight_per_convertion: product.weight_per_convertion ?? undefined, From efec9b62651c30952a635d159cd02610bbc6366a Mon Sep 17 00:00:00 2001 From: rstubryan Date: Mon, 9 Feb 2026 17:05:35 +0700 Subject: [PATCH 4/6] feat(FE): Add formatTitleCaseGeneral helper and update usage --- .../pages/marketing/form/MarketingForm.schema.ts | 8 ++++++-- src/lib/helper.ts | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/components/pages/marketing/form/MarketingForm.schema.ts b/src/components/pages/marketing/form/MarketingForm.schema.ts index 17b6d78c..535395ab 100644 --- a/src/components/pages/marketing/form/MarketingForm.schema.ts +++ b/src/components/pages/marketing/form/MarketingForm.schema.ts @@ -12,7 +12,11 @@ import { BaseSalesOrder, Marketing, } from '@/types/api/marketing/marketing'; -import { formatDate, formatTitleCase } from '@/lib/helper'; +import { + formatDate, + formatTitleCase, + formatTitleCaseGeneral, +} from '@/lib/helper'; type MarketingSchemaType = { customer_id: number | undefined; @@ -119,7 +123,7 @@ export const SalesProductToFieldValues = ( marketing_type: product.marketing_type ? { value: product.marketing_type, - label: formatTitleCase(product.marketing_type), + label: formatTitleCaseGeneral(product.marketing_type), } : null, convertion_unit: product.convertion_unit diff --git a/src/lib/helper.ts b/src/lib/helper.ts index 665c81f1..2804b7d5 100644 --- a/src/lib/helper.ts +++ b/src/lib/helper.ts @@ -45,6 +45,15 @@ export const formatTitleCase = (value: string) => { .join(' '); }; +export const formatTitleCaseGeneral = (value: string) => { + return value + .toLowerCase() + .replace(/_/g, ' ') + .split(' ') + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); +}; + export function formatVechicleNumber(value: string): string { let result = ''; for (let i = 0; i < (value?.length ?? 0); i++) { From e4e6e563c9518e1f58f4705ce013be7c6519a743 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Mon, 9 Feb 2026 17:07:00 +0700 Subject: [PATCH 5/6] refactor(FE): Remove unused helper function `formatTitleCaseGeneral` --- .../pages/marketing/form/MarketingForm.schema.ts | 8 ++------ src/lib/helper.ts | 8 -------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/components/pages/marketing/form/MarketingForm.schema.ts b/src/components/pages/marketing/form/MarketingForm.schema.ts index 535395ab..17b6d78c 100644 --- a/src/components/pages/marketing/form/MarketingForm.schema.ts +++ b/src/components/pages/marketing/form/MarketingForm.schema.ts @@ -12,11 +12,7 @@ import { BaseSalesOrder, Marketing, } from '@/types/api/marketing/marketing'; -import { - formatDate, - formatTitleCase, - formatTitleCaseGeneral, -} from '@/lib/helper'; +import { formatDate, formatTitleCase } from '@/lib/helper'; type MarketingSchemaType = { customer_id: number | undefined; @@ -123,7 +119,7 @@ export const SalesProductToFieldValues = ( marketing_type: product.marketing_type ? { value: product.marketing_type, - label: formatTitleCaseGeneral(product.marketing_type), + label: formatTitleCase(product.marketing_type), } : null, convertion_unit: product.convertion_unit diff --git a/src/lib/helper.ts b/src/lib/helper.ts index 2804b7d5..9a802f80 100644 --- a/src/lib/helper.ts +++ b/src/lib/helper.ts @@ -38,14 +38,6 @@ export const safeRound = (num: number, decimals: number) => { }; export const formatTitleCase = (value: string) => { - return value - .toLowerCase() - .split(' ') - .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) - .join(' '); -}; - -export const formatTitleCaseGeneral = (value: string) => { return value .toLowerCase() .replace(/_/g, ' ') From bcc2070ed2e7453315a42191964d8fd84a4a4587 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Mon, 9 Feb 2026 21:50:35 +0700 Subject: [PATCH 6/6] refactor(FE): Refactor DebtSupplierExportPDF to use reusable PDF components --- .../finance/export/DebtSupllierExportPDF.tsx | 732 +++++------------- 1 file changed, 208 insertions(+), 524 deletions(-) diff --git a/src/components/pages/report/finance/export/DebtSupllierExportPDF.tsx b/src/components/pages/report/finance/export/DebtSupllierExportPDF.tsx index edcd360f..b44c8060 100644 --- a/src/components/pages/report/finance/export/DebtSupllierExportPDF.tsx +++ b/src/components/pages/report/finance/export/DebtSupllierExportPDF.tsx @@ -2,7 +2,6 @@ import { Page, - Text, View, Document, StyleSheet, @@ -12,6 +11,15 @@ import { import { formatDate, formatCurrency, formatNumber } from '@/lib/helper'; import { DebtSupplier } from '@/types/api/report/debt-supplier'; +import { PdfParamBadge } from '@/components/helper/pdf/badge/PdfParamBadge'; +import { PdfTypography } from '@/components/helper/pdf/typography/PdfTypography'; +import { PdfStatusBadge } from '@/components/helper/pdf/badge/PdfStatusBadge'; +import { + PdfTable, + PdfColumn, + PdfTbodyCell, + PdfTfootCell, +} from '@/components/helper/pdf/table'; Font.register({ family: 'Helvetica', @@ -69,133 +77,6 @@ const pdfStyles = StyleSheet.create({ titleSection: { marginBottom: 10, }, - mainTitle: { - fontSize: 14, - fontWeight: 'bold', - marginBottom: 5, - color: '#1f74bf', - }, - supplierTitle: { - fontSize: 12, - fontWeight: 'bold', - marginBottom: 8, - color: '#1f74bf', - }, - supplierInfo: { - fontSize: 9, - marginBottom: 5, - color: '#333333', - }, - 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: 7, - textAlign: 'left', - }, - tableCellNo: { - flex: 0.5, - borderRightWidth: 1, - borderRightColor: '#000000', - borderRightStyle: 'solid', - padding: 4, - fontSize: 7, - textAlign: 'center', - }, - tableCellLast: { - flex: 1, - padding: 4, - fontSize: 7, - }, - tableCellHeader: { - flex: 1, - borderRightWidth: 1, - borderRightColor: '#000000', - borderRightStyle: 'solid', - padding: 4, - fontSize: 7, - 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: 7, - 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: 7, - textAlign: 'right', - }, - tableCellCenter: { - flex: 1, - borderRightWidth: 1, - borderRightColor: '#000000', - borderRightStyle: 'solid', - padding: 4, - fontSize: 7, - textAlign: 'center', - }, - tableBorderBottom: { - borderBottomWidth: 1, - borderBottomColor: '#000000', - borderBottomStyle: 'solid', - }, - summaryRow: { - backgroundColor: '#F0F0F0', - fontWeight: 'bold', - }, - badge: { - paddingVertical: 2, - paddingHorizontal: 4, - borderRadius: 12, - fontSize: 5, - fontWeight: 'bold', - borderWidth: 1, - textAlign: 'center', - whiteSpace: 'nowrap', - }, - parameterBadge: { - backgroundColor: '#F5F5F5', - color: '#333333', - padding: 4, - borderRadius: 4, - fontSize: 8, - marginRight: 8, - marginBottom: 4, - }, parameterContainer: { flexDirection: 'row', flexWrap: 'wrap', @@ -203,6 +84,153 @@ const pdfStyles = StyleSheet.create({ }, }); +const getTableColumns = (): PdfColumn[] => [ + { key: 'no', header: 'No', flex: 0.5, align: 'center' }, + { key: 'pr_number', header: 'No. PR', flex: 1, align: 'left' }, + { key: 'po_number', header: 'No. PO', flex: 1, align: 'left' }, + { + key: 'received_date', + header: 'Tgl Terima/Bayar', + flex: 0.7, + align: 'center', + }, + { key: 'po_date', header: 'Tgl PO', flex: 0.7, align: 'center' }, + { key: 'aging', header: 'Aging', flex: 0.6, align: 'center' }, + { key: 'area', header: 'Area', flex: 1, align: 'left' }, + { key: 'warehouse', header: 'Gudang', flex: 1, align: 'left' }, + { key: 'due_date', header: 'Jatuh Tempo', flex: 1, align: 'center' }, + { key: 'due_status', header: 'Status Jatuh Tempo', flex: 2, align: 'left' }, + { + key: 'total_price', + header: 'Nominal Pembelian (Rp)', + flex: 1.5, + align: 'right', + }, + { + key: 'payment_price', + header: 'Pembayaran (Rp)', + flex: 1.5, + align: 'right', + }, + { + key: 'balance', + header: 'Sisa Saldo Hutang (Rp)', + flex: 1.5, + align: 'right', + }, + { key: 'status', header: 'Status', flex: 1.2, align: 'center' }, + { key: 'travel_number', header: 'No. Perjalanan', flex: 1, align: 'left' }, +]; + +const getTableData = (rows: DebtSupplier['rows']): PdfTbodyCell[][] => { + return rows.map((item, index) => [ + { key: 'no', value: index + 1 }, + { key: 'pr_number', value: item.pr_number || '-' }, + { key: 'po_number', value: item.po_number || '-' }, + { + key: 'received_date', + value: item.received_date + ? formatDate(item.received_date, 'DD MMM YY') + : '-', + }, + { + key: 'po_date', + value: item.po_date ? formatDate(item.po_date, 'DD MMM YY') : '-', + }, + { + key: 'aging', + value: item.aging != null ? `${formatNumber(item.aging)}` : '-', + }, + { key: 'area', value: item.area?.name || '-' }, + { key: 'warehouse', value: item.warehouse?.name || '-' }, + { + key: 'due_date', + value: item.due_date ? formatDate(item.due_date, 'DD MMM YY') : '-', + }, + { + key: 'due_status', + value: + item.due_status && item.due_status !== '-' ? ( + + {item.due_status} + + ) : ( + '-' + ), + }, + { + key: 'total_price', + value: formatCurrency(item.total_price), + align: 'right', + color: item.total_price < 0 ? 'red' : undefined, + }, + { + key: 'payment_price', + value: formatCurrency(item.payment_price), + align: 'right', + color: item.payment_price < 0 ? 'red' : undefined, + }, + { + key: 'balance', + value: formatCurrency(item.balance), + align: 'right', + color: item.balance < 0 ? 'red' : undefined, + }, + { + key: 'status', + value: + item.status && item.status !== '-' ? ( + + + {item.status} + + + ) : ( + '-' + ), + }, + { key: 'travel_number', value: item.travel_number || '-' }, + ]); +}; + +const getTableFooter = (total: DebtSupplier['total']): PdfTfootCell[] => [ + { key: 'no', value: 'Total' }, + { key: 'pr_number', value: '' }, + { key: 'po_number', value: '' }, + { key: 'received_date', value: '' }, + { key: 'po_date', value: '' }, + { key: 'aging', value: formatNumber(total?.aging || 0) + ' Hari' }, + { key: 'area', value: '' }, + { key: 'warehouse', value: '' }, + { key: 'due_date', value: '' }, + { key: 'due_status', value: '' }, + { + key: 'total_price', + value: formatCurrency(total?.total_price || 0), + align: 'right', + }, + { + key: 'payment_price', + value: formatCurrency(total?.payment_price || 0), + align: 'right', + }, + { + key: 'balance', + value: formatCurrency(total?.debt_price || 0), + align: 'right', + }, + { key: 'status', value: '' }, + { key: 'travel_number', value: '' }, +]; + interface DebtSupplierExportPDFParams { data: DebtSupplier[]; params?: { @@ -219,418 +247,74 @@ const createPDFDocument = (params: DebtSupplierExportPDFParams) => { {params.data.map((supplierReport, supplierIndex) => ( {/* Title and Supplier Info */} - + Laporan > Rekapitulasi Hutang ke Supplier - + - - - Periode:{' '} - {params.params?.start_date - ? formatDate(params.params.start_date, 'DD MMM YYYY') - : '-'}{' '} - s.d{' '} - {params.params?.end_date - ? formatDate(params.params.end_date, 'DD MMM YYYY') - : '-'} - - + + Periode:{' '} + {params.params?.start_date + ? formatDate(params.params.start_date, 'DD MMM YYYY') + : '-'}{' '} + s.d{' '} + {params.params?.end_date + ? formatDate(params.params.end_date, 'DD MMM YYYY') + : '-'} + {params.params?.filter_by && ( - - - Filter Tanggal:{' '} - {params.params.filter_by === 'po_date' - ? 'Tanggal PO' - : params.params.filter_by === 'received_date' - ? 'Tanggal Terima' - : params.params.filter_by === 'due_date' - ? 'Tanggal Jatuh Tempo' - : params.params.filter_by} - - + + Filter Tanggal:{' '} + {params.params.filter_by === 'po_date' + ? 'Tanggal PO' + : params.params.filter_by === 'received_date' + ? 'Tanggal Terima' + : params.params.filter_by === 'due_date' + ? 'Tanggal Jatuh Tempo' + : params.params.filter_by} + )} - - - Supplier: {params.params?.supplier_name || 'Semua Supplier'} - - - - - Dicetak: {formatDate(new Date(), 'DD MMM YYYY HH:mm')} - - + + Supplier: {params.params?.supplier_name || 'Semua Supplier'} + + + Dicetak: {formatDate(new Date(), 'DD MMM YYYY HH:mm')} + - + {supplierReport.supplier.name} - - + + {supplierReport.supplier.category} - + {/* Table */} - - {/* Table Header */} - - - No - - - No. PR - - - No. PO - - - Tgl Terima/Bayar - - - Tgl PO - - - Aging - - - Area - - - Gudang - - - Jatuh Tempo - - - Status Jatuh Tempo - - - Nominal Pembelian (Rp) - - - Pembayaran (Rp) - - - Sisa Saldo Hutang (Rp) - - - Status - - - No. Perjalanan - - - - {/* Initial Balance Row */} - - - {/* NO */} - - - {/* No. PR */} - - - {/* No. PO */} - - - {/* Tgl Terima/Bayar */} - - - {/* Tgl PO */} - - - {/* Aging */} - - - {/* Area */} - - - {/* Gudang */} - - - {/* Jatuh Tempo */} - - - {/* Status Jatuh Tempo */} - - - {/* Nominal Pembelian (Rp) */} - - - {/* Pembayaran (Rp) */} - - - - {' '} - {/* Sisa Saldo Hutang (Rp) */} - {formatCurrency(supplierReport.initial_balance || 0)} - - - - {/* Status */} - - - - - - - {/* Table Body */} - {supplierReport.rows.map((item, index) => ( - - - {index + 1} - - - {item.pr_number || '-'} - - - {item.po_number || '-'} - - - - {item.received_date - ? item.received_date != '-' - ? formatDate(item.received_date, 'DD MMM YY') - : '-' - : '-'} - - - - - {item.po_date - ? item.po_date != '-' - ? formatDate(item.po_date, 'DD MMM YY') - : '-' - : '-'} - - - - {formatNumber(item.aging)} Hari - - - {item.area?.name || '-'} - - - {item.warehouse?.name || '-'} - - - - {item.due_date - ? item.due_date != '-' - ? formatDate(item.due_date, 'DD MMM YY') - : '-' - : '-'} - - - - {item.due_status && item.due_status !== '-' ? ( - - - {item.due_status} - - - ) : ( - - - )} - - - {formatCurrency(item.total_price)} - - - {formatCurrency(item.payment_price)} - - - {formatCurrency(item.balance)} - - - {item.status && item.status !== '-' ? ( - - - {item.status} - - - ) : ( - - - )} - - - {item.travel_number || '-'} - - - ))} - - {/* Summary Row */} - {supplierReport.total && ( - - - Total - - - - - - - - - - - - - - - {formatNumber(supplierReport.total.aging)} Hari - - - - - - - - - - - - - - - - {formatCurrency(supplierReport.total.total_price)} - - - - - {formatCurrency(supplierReport.total.payment_price)} - - - - {formatCurrency(supplierReport.total.debt_price)} - - - - - - - - - )} - + } + : undefined + } + /> ))}