mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 15:25:46 +00:00
Merge branch 'feat/reusable-pdf-component' into 'development'
[FEAT/FE] Reusable PDF Component and Hotfix Penjualan See merge request mbugroup/lti-web-client!320
This commit is contained in:
@@ -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 (
|
||||||
|
<View style={styles.parameterBadge}>
|
||||||
|
<Text>{children}</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -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 (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.statusBadge,
|
||||||
|
{
|
||||||
|
backgroundColor,
|
||||||
|
borderColor,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Text style={[styles.statusBadgeText, { color: textColor }]}>
|
||||||
|
{children}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -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<TypographyVariant, string> = {
|
||||||
|
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 (
|
||||||
|
<Text style={[sizeStyle, { color: textColor }, customStyle]}>
|
||||||
|
{children}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -198,6 +198,13 @@ const SalesOrderFormModal = ({
|
|||||||
: 'KG' // termasuk "QTY" dan "KG"
|
: 'KG' // termasuk "QTY" dan "KG"
|
||||||
: undefined;
|
: 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 {
|
return {
|
||||||
vehicle_number: product.vehicle_number as string,
|
vehicle_number: product.vehicle_number as string,
|
||||||
kandang_id: product.kandang_id as number,
|
kandang_id: product.kandang_id as number,
|
||||||
@@ -207,8 +214,7 @@ const SalesOrderFormModal = ({
|
|||||||
qty: parseFloat(String(product.qty || 0)),
|
qty: parseFloat(String(product.qty || 0)),
|
||||||
avg_weight: parseFloat(String(product.avg_weight || 0)),
|
avg_weight: parseFloat(String(product.avg_weight || 0)),
|
||||||
total_price: parseFloat(String(product.total_price || 0)),
|
total_price: parseFloat(String(product.total_price || 0)),
|
||||||
marketing_type:
|
marketing_type: marketingTypeValue,
|
||||||
product.marketing_type?.value?.toUpperCase() || '',
|
|
||||||
convertion_unit: normalizedConvertionUnit,
|
convertion_unit: normalizedConvertionUnit,
|
||||||
weight_per_convertion:
|
weight_per_convertion:
|
||||||
product.weight_per_convertion ?? undefined,
|
product.weight_per_convertion ?? undefined,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Page,
|
Page,
|
||||||
Text,
|
|
||||||
View,
|
View,
|
||||||
Document,
|
Document,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
@@ -18,6 +17,9 @@ import {
|
|||||||
PdfTbodyCell,
|
PdfTbodyCell,
|
||||||
PdfTfootCell,
|
PdfTfootCell,
|
||||||
} from '@/components/helper/pdf/table';
|
} 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({
|
Font.register({
|
||||||
family: 'Helvetica',
|
family: 'Helvetica',
|
||||||
@@ -34,53 +36,6 @@ const pdfStyles = StyleSheet.create({
|
|||||||
titleSection: {
|
titleSection: {
|
||||||
marginBottom: 10,
|
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: {
|
parameterContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flexWrap: 'wrap',
|
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[] => [
|
const getTableColumns = (): PdfColumn[] => [
|
||||||
{ key: 'no', header: 'No', flex: 0.5, align: 'center' },
|
{ key: 'no', header: 'No', flex: 0.5, align: 'center' },
|
||||||
{ key: 'trans_date', header: 'Tanggal DO', flex: 1.2, align: 'center' },
|
{ key: 'trans_date', header: 'Tanggal DO', flex: 1.2, align: 'center' },
|
||||||
@@ -221,15 +144,14 @@ const getTableData = (
|
|||||||
{
|
{
|
||||||
key: 'status',
|
key: 'status',
|
||||||
value: item.status ? (
|
value: item.status ? (
|
||||||
<View
|
<View style={{ alignItems: 'center' }}>
|
||||||
style={[
|
<PdfStatusBadge
|
||||||
pdfStyles.badge,
|
backgroundColor={item.status === 'LUNAS' ? '#DBEAFE' : '#FEE2E2'}
|
||||||
item.status === 'LUNAS'
|
textColor={item.status === 'LUNAS' ? '#1E40AF' : '#991B1B'}
|
||||||
? pdfStyles.badgeLunas
|
borderColor={item.status === 'LUNAS' ? '#60A5FA' : '#F87171'}
|
||||||
: pdfStyles.badgeBelumLunas,
|
>
|
||||||
]}
|
{item.status === 'LUNAS' ? 'Lunas' : 'Belum Lunas'}
|
||||||
>
|
</PdfStatusBadge>
|
||||||
<Text>{item.status === 'LUNAS' ? 'Lunas' : 'Belum Lunas'}</Text>
|
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
'-'
|
'-'
|
||||||
@@ -302,43 +224,37 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
|
|||||||
>
|
>
|
||||||
{/* Title and Parameters */}
|
{/* Title and Parameters */}
|
||||||
<View style={pdfStyles.titleSection}>
|
<View style={pdfStyles.titleSection}>
|
||||||
<Text style={pdfStyles.mainTitle}>
|
<PdfTypography size='h1' variant='primary'>
|
||||||
Laporan > Kontrol Pembayaran Customer
|
Laporan > Kontrol Pembayaran Customer
|
||||||
</Text>
|
</PdfTypography>
|
||||||
<View style={pdfStyles.parameterContainer}>
|
<View style={pdfStyles.parameterContainer}>
|
||||||
<View style={pdfStyles.parameterBadge}>
|
<PdfParamBadge>
|
||||||
<Text>
|
Periode:{' '}
|
||||||
Periode:{' '}
|
{params.params?.start_date
|
||||||
{params.params?.start_date
|
? formatDate(params.params.start_date, 'DD MMM YYYY')
|
||||||
? formatDate(params.params.start_date, 'DD MMM YYYY')
|
: '-'}{' '}
|
||||||
: '-'}{' '}
|
s.d{' '}
|
||||||
s.d{' '}
|
{params.params?.end_date
|
||||||
{params.params?.end_date
|
? formatDate(params.params.end_date, 'DD MMM YYYY')
|
||||||
? formatDate(params.params.end_date, 'DD MMM YYYY')
|
: '-'}
|
||||||
: '-'}
|
</PdfParamBadge>
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
{/* TODO: Uncomment when BE is ready */}
|
{/* TODO: Uncomment when BE is ready */}
|
||||||
{/* <View style={pdfStyles.parameterBadge}>
|
{/* <PdfParamBadge>
|
||||||
<Text>Filter Tanggal: Tanggal DO</Text>
|
Filter Tanggal: Tanggal DO
|
||||||
</View> */}
|
</PdfParamBadge> */}
|
||||||
<View style={pdfStyles.parameterBadge}>
|
<PdfParamBadge>
|
||||||
<Text>
|
Customer: {params.params?.customer_name || 'Semua Customer'}
|
||||||
Customer: {params.params?.customer_name || 'Semua Customer'}
|
</PdfParamBadge>
|
||||||
</Text>
|
<PdfParamBadge>
|
||||||
</View>
|
Dicetak: {formatDate(new Date(), 'DD MMM YYYY HH:mm')}
|
||||||
<View style={pdfStyles.parameterBadge}>
|
</PdfParamBadge>
|
||||||
<Text>
|
|
||||||
Dicetak: {formatDate(new Date(), 'DD MMM YYYY HH:mm')}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
<Text style={pdfStyles.supplierTitle}>
|
<PdfTypography size='h2' variant='primary'>
|
||||||
{customerReport.customer.name}
|
{customerReport.customer.name}
|
||||||
</Text>
|
</PdfTypography>
|
||||||
<Text style={pdfStyles.supplierInfo}>
|
<PdfTypography size='label'>
|
||||||
Alamat: {customerReport.customer.address || '-'}
|
Alamat: {customerReport.customer.address || '-'}
|
||||||
</Text>
|
</PdfTypography>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Table */}
|
{/* Table */}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Page,
|
Page,
|
||||||
Text,
|
|
||||||
View,
|
View,
|
||||||
Document,
|
Document,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
@@ -12,6 +11,15 @@ import {
|
|||||||
|
|
||||||
import { formatDate, formatCurrency, formatNumber } from '@/lib/helper';
|
import { formatDate, formatCurrency, formatNumber } from '@/lib/helper';
|
||||||
import { DebtSupplier } from '@/types/api/report/debt-supplier';
|
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({
|
Font.register({
|
||||||
family: 'Helvetica',
|
family: 'Helvetica',
|
||||||
@@ -69,133 +77,6 @@ const pdfStyles = StyleSheet.create({
|
|||||||
titleSection: {
|
titleSection: {
|
||||||
marginBottom: 10,
|
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: {
|
parameterContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flexWrap: 'wrap',
|
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 !== '-' ? (
|
||||||
|
<PdfStatusBadge
|
||||||
|
backgroundColor={getPDFBadgeStyle(item.due_status, 'due').bg}
|
||||||
|
textColor={getPDFBadgeStyle(item.due_status, 'due').text}
|
||||||
|
borderColor={getPDFBadgeStyle(item.due_status, 'due').border}
|
||||||
|
>
|
||||||
|
{item.due_status}
|
||||||
|
</PdfStatusBadge>
|
||||||
|
) : (
|
||||||
|
'-'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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 !== '-' ? (
|
||||||
|
<View style={{ alignItems: 'center' }}>
|
||||||
|
<PdfStatusBadge
|
||||||
|
backgroundColor={getPDFBadgeStyle(item.status, 'payment').bg}
|
||||||
|
textColor={getPDFBadgeStyle(item.status, 'payment').text}
|
||||||
|
borderColor={getPDFBadgeStyle(item.status, 'payment').border}
|
||||||
|
>
|
||||||
|
{item.status}
|
||||||
|
</PdfStatusBadge>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
'-'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{ 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 {
|
interface DebtSupplierExportPDFParams {
|
||||||
data: DebtSupplier[];
|
data: DebtSupplier[];
|
||||||
params?: {
|
params?: {
|
||||||
@@ -219,418 +247,74 @@ const createPDFDocument = (params: DebtSupplierExportPDFParams) => {
|
|||||||
{params.data.map((supplierReport, supplierIndex) => (
|
{params.data.map((supplierReport, supplierIndex) => (
|
||||||
<Page
|
<Page
|
||||||
key={supplierIndex}
|
key={supplierIndex}
|
||||||
size='A4'
|
size='A3'
|
||||||
orientation='landscape'
|
orientation='landscape'
|
||||||
style={pdfStyles.page}
|
style={pdfStyles.page}
|
||||||
>
|
>
|
||||||
{/* Title and Supplier Info */}
|
{/* Title and Supplier Info */}
|
||||||
<View style={pdfStyles.titleSection}>
|
<View style={pdfStyles.titleSection}>
|
||||||
<Text style={pdfStyles.mainTitle}>
|
<PdfTypography size='h1' variant='primary'>
|
||||||
Laporan > Rekapitulasi Hutang ke Supplier
|
Laporan > Rekapitulasi Hutang ke Supplier
|
||||||
</Text>
|
</PdfTypography>
|
||||||
<View style={pdfStyles.parameterContainer}>
|
<View style={pdfStyles.parameterContainer}>
|
||||||
<View style={pdfStyles.parameterBadge}>
|
<PdfParamBadge>
|
||||||
<Text>
|
Periode:{' '}
|
||||||
Periode:{' '}
|
{params.params?.start_date
|
||||||
{params.params?.start_date
|
? formatDate(params.params.start_date, 'DD MMM YYYY')
|
||||||
? formatDate(params.params.start_date, 'DD MMM YYYY')
|
: '-'}{' '}
|
||||||
: '-'}{' '}
|
s.d{' '}
|
||||||
s.d{' '}
|
{params.params?.end_date
|
||||||
{params.params?.end_date
|
? formatDate(params.params.end_date, 'DD MMM YYYY')
|
||||||
? formatDate(params.params.end_date, 'DD MMM YYYY')
|
: '-'}
|
||||||
: '-'}
|
</PdfParamBadge>
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
{params.params?.filter_by && (
|
{params.params?.filter_by && (
|
||||||
<View style={pdfStyles.parameterBadge}>
|
<PdfParamBadge>
|
||||||
<Text>
|
Filter Tanggal:{' '}
|
||||||
Filter Tanggal:{' '}
|
{params.params.filter_by === 'po_date'
|
||||||
{params.params.filter_by === 'po_date'
|
? 'Tanggal PO'
|
||||||
? 'Tanggal PO'
|
: params.params.filter_by === 'received_date'
|
||||||
: params.params.filter_by === 'received_date'
|
? 'Tanggal Terima'
|
||||||
? 'Tanggal Terima'
|
: params.params.filter_by === 'due_date'
|
||||||
: params.params.filter_by === 'due_date'
|
? 'Tanggal Jatuh Tempo'
|
||||||
? 'Tanggal Jatuh Tempo'
|
: params.params.filter_by}
|
||||||
: params.params.filter_by}
|
</PdfParamBadge>
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
)}
|
)}
|
||||||
<View style={pdfStyles.parameterBadge}>
|
<PdfParamBadge>
|
||||||
<Text>
|
Supplier: {params.params?.supplier_name || 'Semua Supplier'}
|
||||||
Supplier: {params.params?.supplier_name || 'Semua Supplier'}
|
</PdfParamBadge>
|
||||||
</Text>
|
<PdfParamBadge>
|
||||||
</View>
|
Dicetak: {formatDate(new Date(), 'DD MMM YYYY HH:mm')}
|
||||||
<View style={pdfStyles.parameterBadge}>
|
</PdfParamBadge>
|
||||||
<Text>
|
|
||||||
Dicetak: {formatDate(new Date(), 'DD MMM YYYY HH:mm')}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
<Text style={pdfStyles.supplierTitle}>
|
<PdfTypography size='h2' variant='primary'>
|
||||||
{supplierReport.supplier.name}
|
{supplierReport.supplier.name}
|
||||||
</Text>
|
</PdfTypography>
|
||||||
<Text style={pdfStyles.supplierInfo}>
|
<PdfTypography size='label'>
|
||||||
{supplierReport.supplier.category}
|
{supplierReport.supplier.category}
|
||||||
</Text>
|
</PdfTypography>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Table */}
|
{/* Table */}
|
||||||
<View style={pdfStyles.table}>
|
<PdfTable
|
||||||
{/* Table Header */}
|
columns={getTableColumns()}
|
||||||
<View style={[pdfStyles.tableRow, pdfStyles.tableHeader]}>
|
data={getTableData(supplierReport.rows)}
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 0.5 }]}>
|
footer={
|
||||||
<Text>No</Text>
|
supplierReport.total
|
||||||
</View>
|
? getTableFooter(supplierReport.total)
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 1 }]}>
|
: undefined
|
||||||
<Text>No. PR</Text>
|
}
|
||||||
</View>
|
firstRow={
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 1 }]}>
|
typeof supplierReport.initial_balance === 'number' &&
|
||||||
<Text>No. PO</Text>
|
supplierReport.initial_balance !== 0
|
||||||
</View>
|
? {
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 0.7 }]}>
|
valueKey: 'balance',
|
||||||
<Text>Tgl Terima/Bayar</Text>
|
value: supplierReport.initial_balance,
|
||||||
</View>
|
align: 'right',
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 0.7 }]}>
|
|
||||||
<Text>Tgl PO</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 0.6 }]}>
|
|
||||||
<Text>Aging</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 1 }]}>
|
|
||||||
<Text>Area</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 1 }]}>
|
|
||||||
<Text>Gudang</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 1 }]}>
|
|
||||||
<Text>Jatuh Tempo</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 2 }]}>
|
|
||||||
<Text>Status Jatuh Tempo</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.5 }]}>
|
|
||||||
<Text>Nominal Pembelian (Rp)</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.5 }]}>
|
|
||||||
<Text>Pembayaran (Rp)</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.5 }]}>
|
|
||||||
<Text>Sisa Saldo Hutang (Rp)</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 1.2 }]}>
|
|
||||||
<Text>Status</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
pdfStyles.tableCellHeader,
|
|
||||||
{ flex: 1, borderRight: 'none' },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Text>No. Perjalanan</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{/* Initial Balance Row */}
|
|
||||||
<View style={[pdfStyles.tableRow, pdfStyles.tableBorderBottom]}>
|
|
||||||
<View style={[pdfStyles.tableCellNo, { flex: 0.5 }]}>
|
|
||||||
<Text></Text> {/* NO */}
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
|
||||||
<Text></Text> {/* No. PR */}
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
|
||||||
<Text></Text> {/* No. PO */}
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellCenter, { flex: 0.7 }]}>
|
|
||||||
<Text></Text> {/* Tgl Terima/Bayar */}
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellCenter, { flex: 0.7 }]}>
|
|
||||||
<Text></Text> {/* Tgl PO */}
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellCenter, { flex: 0.6 }]}>
|
|
||||||
<Text></Text> {/* Aging */}
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
|
||||||
<Text></Text> {/* Area */}
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
|
||||||
<Text></Text> {/* Gudang */}
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellCenter, { flex: 1 }]}>
|
|
||||||
<Text></Text> {/* Jatuh Tempo */}
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 2 }]}>
|
|
||||||
<Text></Text> {/* Status Jatuh Tempo */}
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1.5 }]}>
|
|
||||||
<Text></Text> {/* Nominal Pembelian (Rp) */}
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1.5 }]}>
|
|
||||||
<Text></Text> {/* Pembayaran (Rp) */}
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
pdfStyles.tableCellRight,
|
|
||||||
{
|
|
||||||
flex: 1.5,
|
|
||||||
color: supplierReport.initial_balance < 0 ? 'red' : 'black',
|
color: supplierReport.initial_balance < 0 ? 'red' : 'black',
|
||||||
},
|
}
|
||||||
]}
|
: undefined
|
||||||
>
|
}
|
||||||
<Text>
|
/>
|
||||||
{' '}
|
|
||||||
{/* Sisa Saldo Hutang (Rp) */}
|
|
||||||
{formatCurrency(supplierReport.initial_balance || 0)}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1.2 }]}>
|
|
||||||
<Text></Text> {/* Status */}
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
pdfStyles.tableCell, // No. Perjalanan
|
|
||||||
{ flex: 1, borderRight: 'none' },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Text></Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{/* Table Body */}
|
|
||||||
{supplierReport.rows.map((item, index) => (
|
|
||||||
<View
|
|
||||||
key={index}
|
|
||||||
style={[
|
|
||||||
pdfStyles.tableRow,
|
|
||||||
index < supplierReport.rows.length - 1
|
|
||||||
? pdfStyles.tableBorderBottom
|
|
||||||
: {},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<View style={[pdfStyles.tableCellNo, { flex: 0.5 }]}>
|
|
||||||
<Text>{index + 1}</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
|
||||||
<Text>{item.pr_number || '-'}</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
|
||||||
<Text>{item.po_number || '-'}</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellCenter, { flex: 0.7 }]}>
|
|
||||||
<Text>
|
|
||||||
{item.received_date
|
|
||||||
? item.received_date != '-'
|
|
||||||
? formatDate(item.received_date, 'DD MMM YY')
|
|
||||||
: '-'
|
|
||||||
: '-'}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellCenter, { flex: 0.7 }]}>
|
|
||||||
<Text>
|
|
||||||
{item.po_date
|
|
||||||
? item.po_date != '-'
|
|
||||||
? formatDate(item.po_date, 'DD MMM YY')
|
|
||||||
: '-'
|
|
||||||
: '-'}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellCenter, { flex: 0.6 }]}>
|
|
||||||
<Text>{formatNumber(item.aging)} Hari</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
|
||||||
<Text>{item.area?.name || '-'}</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
|
||||||
<Text>{item.warehouse?.name || '-'}</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellCenter, { flex: 1 }]}>
|
|
||||||
<Text>
|
|
||||||
{item.due_date
|
|
||||||
? item.due_date != '-'
|
|
||||||
? formatDate(item.due_date, 'DD MMM YY')
|
|
||||||
: '-'
|
|
||||||
: '-'}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 2 }]}>
|
|
||||||
{item.due_status && item.due_status !== '-' ? (
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
pdfStyles.badge,
|
|
||||||
{
|
|
||||||
backgroundColor: getPDFBadgeStyle(
|
|
||||||
item.due_status,
|
|
||||||
'due'
|
|
||||||
).bg,
|
|
||||||
borderColor: getPDFBadgeStyle(item.due_status, 'due')
|
|
||||||
.border,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
color: getPDFBadgeStyle(item.due_status, 'due').text,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{item.due_status}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
) : (
|
|
||||||
<Text>-</Text>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
pdfStyles.tableCellRight,
|
|
||||||
{
|
|
||||||
flex: 1.5,
|
|
||||||
color: item.total_price < 0 ? 'red' : 'black',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Text>{formatCurrency(item.total_price)}</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
pdfStyles.tableCellRight,
|
|
||||||
{
|
|
||||||
flex: 1.5,
|
|
||||||
color: item.payment_price < 0 ? 'red' : 'black',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Text>{formatCurrency(item.payment_price)}</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
pdfStyles.tableCellRight,
|
|
||||||
{ flex: 1.5, color: item.balance < 0 ? 'red' : 'black' },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Text>{formatCurrency(item.balance)}</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1.2 }]}>
|
|
||||||
{item.status && item.status !== '-' ? (
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
pdfStyles.badge,
|
|
||||||
{
|
|
||||||
backgroundColor: getPDFBadgeStyle(
|
|
||||||
item.status,
|
|
||||||
'payment'
|
|
||||||
).bg,
|
|
||||||
borderColor: getPDFBadgeStyle(item.status, 'payment')
|
|
||||||
.border,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
color: getPDFBadgeStyle(item.status, 'payment').text,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{item.status}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
) : (
|
|
||||||
<Text>-</Text>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
pdfStyles.tableCell, // No. Perjalanan
|
|
||||||
{ flex: 1, borderRight: 'none' },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Text>{item.travel_number || '-'}</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{/* Summary Row */}
|
|
||||||
{supplierReport.total && (
|
|
||||||
<View style={[pdfStyles.tableRow, pdfStyles.summaryRow]}>
|
|
||||||
<View style={[pdfStyles.tableCellNo, { flex: 0.5 }]}>
|
|
||||||
<Text>Total</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
|
||||||
<Text></Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
|
||||||
<Text></Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 0.7 }]}>
|
|
||||||
<Text></Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 0.7 }]}>
|
|
||||||
<Text></Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellCenter, { flex: 0.6 }]}>
|
|
||||||
<Text>{formatNumber(supplierReport.total.aging)} Hari</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
|
||||||
<Text></Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
|
||||||
<Text></Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
|
||||||
<Text></Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 2 }]}>
|
|
||||||
<Text></Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
pdfStyles.tableCellRight,
|
|
||||||
{
|
|
||||||
flex: 1.5,
|
|
||||||
color:
|
|
||||||
supplierReport.total.total_price < 0 ? 'red' : 'black',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Text>
|
|
||||||
{formatCurrency(supplierReport.total.total_price)}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
pdfStyles.tableCellRight,
|
|
||||||
{
|
|
||||||
flex: 1.5,
|
|
||||||
color:
|
|
||||||
supplierReport.total.payment_price < 0
|
|
||||||
? 'red'
|
|
||||||
: 'black',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Text>
|
|
||||||
{formatCurrency(supplierReport.total.payment_price)}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
pdfStyles.tableCellRight,
|
|
||||||
{
|
|
||||||
flex: 1.5,
|
|
||||||
color:
|
|
||||||
supplierReport.total.debt_price < 0 ? 'red' : 'black',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Text>{formatCurrency(supplierReport.total.debt_price)}</Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1.2 }]}>
|
|
||||||
<Text></Text>
|
|
||||||
</View>
|
|
||||||
<View style={[pdfStyles.tableCellLast, { flex: 1 }]}>
|
|
||||||
<Text></Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</Page>
|
</Page>
|
||||||
))}
|
))}
|
||||||
</Document>
|
</Document>
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export const safeRound = (num: number, decimals: number) => {
|
|||||||
export const formatTitleCase = (value: string) => {
|
export const formatTitleCase = (value: string) => {
|
||||||
return value
|
return value
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
|
.replace(/_/g, ' ')
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||||
.join(' ');
|
.join(' ');
|
||||||
|
|||||||
Reference in New Issue
Block a user