refactor(FE): Refactor PdfTable components to support generic data types

This commit is contained in:
rstubryan
2026-02-11 10:38:51 +07:00
parent 02d13efc25
commit 70b63f7773
6 changed files with 167 additions and 123 deletions
+48 -38
View File
@@ -1,21 +1,8 @@
'use client';
import { Text, View, StyleSheet } from '@react-pdf/renderer';
export interface PdfColumn {
key: string;
header: string;
flex: number;
align?: 'left' | 'center' | 'right';
}
export interface PdfTfootCell {
key: string;
value: string | number;
align?: 'left' | 'center' | 'right';
flex?: number;
color?: string;
}
import { ReactNode } from 'react';
import type { PdfColumn } from './types';
const styles = StyleSheet.create({
tableRow: {
@@ -69,63 +56,86 @@ const styles = StyleSheet.create({
},
});
interface PdfTfootProps {
columns: PdfColumn[];
cells: PdfTfootCell[];
interface PdfTfootProps<TData = Record<string, unknown>> {
columns: PdfColumn<TData>[];
data: TData[];
label?: string;
}
export const PdfTfoot = ({
export const PdfTfoot = <TData = Record<string, unknown>,>({
columns,
cells,
data,
label = 'Total',
}: PdfTfootProps) => {
}: PdfTfootProps<TData>) => {
return (
<View style={[styles.tableRow, styles.summaryRow]}>
{columns.map((column, index) => {
const isLastColumn = index === columns.length - 1;
const cellData = cells.find((c) => c.key === column.key);
// Get footer content from column definition
let footerContent: ReactNode;
if (typeof column.footer === 'function') {
footerContent = column.footer(data);
} else {
footerContent = column.footer;
}
// Use label for first column (usually 'no' column)
const displayContent = column.key === 'no' ? label : footerContent;
// Determine alignment
const align = column.footerAlign || column.align || 'left';
const color = column.footerColor || 'black';
const cellStyle =
column.key === 'no'
? [
styles.tableCellNo,
{ flex: column.flex, borderRightWidth: isLastColumn ? 0 : 1 },
{
flex: column.flex || 1,
borderRightWidth: isLastColumn ? 0 : 1,
color,
},
]
: cellData?.align === 'right'
: align === 'right'
? [
styles.tableCellRight,
{
flex: column.flex,
color: cellData?.color || 'black',
flex: column.flex || 1,
color,
borderRightWidth: isLastColumn ? 0 : 1,
},
]
: cellData?.align === 'center'
: align === 'center'
? [
styles.tableCellCenter,
{
flex: column.flex,
color: cellData?.color || 'black',
flex: column.flex || 1,
color,
borderRightWidth: isLastColumn ? 0 : 1,
},
]
: isLastColumn
? [styles.tableCellLast, { flex: column.flex }]
: [
styles.tableCell,
{
flex: column.flex,
color: cellData?.color || 'black',
},
];
? [styles.tableCellLast, { flex: column.flex || 1, color }]
: [styles.tableCell, { flex: column.flex || 1, color }];
return (
<View key={column.key} style={cellStyle}>
<Text>{column.key === 'no' ? label : cellData?.value || ''}</Text>
{displayContent !== undefined && displayContent !== null ? (
typeof displayContent === 'string' ||
typeof displayContent === 'number' ? (
<Text>{String(displayContent)}</Text>
) : (
displayContent
)
) : (
<Text>-</Text>
)}
</View>
);
})}
</View>
);
};
export type { PdfColumn };