mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-25 15:55:48 +00:00
refactor(FE): Refactor PdfTable components to support generic data types
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { View, StyleSheet } from '@react-pdf/renderer';
|
import { View, StyleSheet } from '@react-pdf/renderer';
|
||||||
import { PdfThead, PdfColumn } from './PdfThead';
|
import type { PdfColumn } from './types';
|
||||||
import { PdfTbody, PdfTbodyCell } from './PdfTbody';
|
import { PdfThead } from './PdfThead';
|
||||||
import { PdfTfoot, PdfTfootCell } from './PdfTfoot';
|
import { PdfTbody } from './PdfTbody';
|
||||||
|
import { PdfTfoot } from './PdfTfoot';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
table: {
|
table: {
|
||||||
@@ -13,10 +14,10 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface PdfTableProps {
|
interface PdfTableProps<TData = Record<string, unknown>> {
|
||||||
columns: PdfColumn[];
|
columns: PdfColumn<TData>[];
|
||||||
data: PdfTbodyCell[][];
|
data: TData[];
|
||||||
footer?: PdfTfootCell[];
|
showFooter?: boolean;
|
||||||
footerLabel?: string;
|
footerLabel?: string;
|
||||||
firstRow?: {
|
firstRow?: {
|
||||||
valueKey: string;
|
valueKey: string;
|
||||||
@@ -26,20 +27,26 @@ interface PdfTableProps {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PdfTable = ({
|
export const PdfTable = <TData = Record<string, unknown>,>({
|
||||||
columns,
|
columns,
|
||||||
data,
|
data,
|
||||||
footer,
|
showFooter = false,
|
||||||
footerLabel = 'Total',
|
footerLabel = 'Total',
|
||||||
firstRow,
|
firstRow,
|
||||||
}: PdfTableProps) => {
|
}: PdfTableProps<TData>) => {
|
||||||
|
// Check if any column has footer defined
|
||||||
|
const hasFooter =
|
||||||
|
showFooter || columns.some((col) => col.footer !== undefined);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.table}>
|
<View style={styles.table}>
|
||||||
<PdfThead columns={columns} />
|
<PdfThead columns={columns} data={data} />
|
||||||
<PdfTbody columns={columns} rows={data} firstRow={firstRow} />
|
<PdfTbody columns={columns} data={data} firstRow={firstRow} />
|
||||||
{footer && footer.length > 0 && (
|
{hasFooter && data.length > 0 && (
|
||||||
<PdfTfoot columns={columns} cells={footer} label={footerLabel} />
|
<PdfTfoot columns={columns} data={data} label={footerLabel} />
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type { PdfColumn };
|
||||||
|
|||||||
@@ -1,22 +1,8 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Text, View, StyleSheet } from '@react-pdf/renderer';
|
import { Text, View, StyleSheet } from '@react-pdf/renderer';
|
||||||
|
import { ReactNode } from 'react';
|
||||||
export interface PdfColumn {
|
import type { PdfColumn } from './types';
|
||||||
key: string;
|
|
||||||
header: string;
|
|
||||||
flex: number;
|
|
||||||
align?: 'left' | 'center' | 'right';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PdfTbodyCell {
|
|
||||||
key: string;
|
|
||||||
value: string | number | React.ReactNode;
|
|
||||||
align?: 'left' | 'center' | 'right';
|
|
||||||
color?: string;
|
|
||||||
formatAs?: 'text' | 'date' | 'currency' | 'number';
|
|
||||||
formatDate?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
tableRow: {
|
tableRow: {
|
||||||
@@ -71,21 +57,22 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface PdfTbodyProps {
|
interface PdfTbodyProps<TData = Record<string, unknown>> {
|
||||||
columns: PdfColumn[];
|
columns: PdfColumn<TData>[];
|
||||||
rows: PdfTbodyCell[][];
|
data: TData[];
|
||||||
firstRow?: {
|
firstRow?: {
|
||||||
valueKey: string;
|
valueKey: string;
|
||||||
value: number;
|
value: number;
|
||||||
align?: 'right';
|
align?: 'right';
|
||||||
color?: string;
|
color?: string;
|
||||||
};
|
};
|
||||||
formatDate?: (date: string, format: string) => string;
|
|
||||||
formatNumber?: (num: number) => string;
|
|
||||||
formatCurrency?: (num: number) => string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
|
export const PdfTbody = <TData = Record<string, unknown>,>({
|
||||||
|
columns,
|
||||||
|
data,
|
||||||
|
firstRow,
|
||||||
|
}: PdfTbodyProps<TData>) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* First Row */}
|
{/* First Row */}
|
||||||
@@ -93,17 +80,17 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
|
|||||||
<View style={[styles.tableRow, styles.tableBorderBottom]}>
|
<View style={[styles.tableRow, styles.tableBorderBottom]}>
|
||||||
{columns.map((column, index) => {
|
{columns.map((column, index) => {
|
||||||
const isLastColumn = index === columns.length - 1;
|
const isLastColumn = index === columns.length - 1;
|
||||||
const isfirstRowColumn = column.key === firstRow.valueKey;
|
const isFirstRowColumn = column.key === firstRow.valueKey;
|
||||||
const align = column.align || 'center';
|
const align = column.align || 'left';
|
||||||
|
|
||||||
const cellStyle =
|
const cellStyle =
|
||||||
column.key === 'no'
|
column.key === 'no'
|
||||||
? [styles.tableCellNo, { flex: column.flex }]
|
? [styles.tableCellNo, { flex: column.flex || 1 }]
|
||||||
: isfirstRowColumn
|
: isFirstRowColumn
|
||||||
? [
|
? [
|
||||||
styles.tableCellRight,
|
styles.tableCellRight,
|
||||||
{
|
{
|
||||||
flex: column.flex,
|
flex: column.flex || 1,
|
||||||
color: firstRow.color || 'black',
|
color: firstRow.color || 'black',
|
||||||
borderRightWidth: isLastColumn ? 0 : 1,
|
borderRightWidth: isLastColumn ? 0 : 1,
|
||||||
},
|
},
|
||||||
@@ -112,7 +99,7 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
|
|||||||
? [
|
? [
|
||||||
styles.tableCellRight,
|
styles.tableCellRight,
|
||||||
{
|
{
|
||||||
flex: column.flex,
|
flex: column.flex || 1,
|
||||||
borderRightWidth: isLastColumn ? 0 : 1,
|
borderRightWidth: isLastColumn ? 0 : 1,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@@ -120,7 +107,7 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
|
|||||||
? [
|
? [
|
||||||
styles.tableCellCenter,
|
styles.tableCellCenter,
|
||||||
{
|
{
|
||||||
flex: column.flex,
|
flex: column.flex || 1,
|
||||||
borderRightWidth: isLastColumn ? 0 : 1,
|
borderRightWidth: isLastColumn ? 0 : 1,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@@ -128,15 +115,15 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
|
|||||||
? [
|
? [
|
||||||
styles.tableCellLast,
|
styles.tableCellLast,
|
||||||
{
|
{
|
||||||
flex: column.flex,
|
flex: column.flex || 1,
|
||||||
borderRightWidth: 0,
|
borderRightWidth: 0,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
: [styles.tableCell, { flex: column.flex }];
|
: [styles.tableCell, { flex: column.flex || 1 }];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View key={column.key} style={cellStyle}>
|
<View key={column.key} style={cellStyle}>
|
||||||
<Text>{isfirstRowColumn ? firstRow.value : ''}</Text>
|
<Text>{isFirstRowColumn ? firstRow.value : ''}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -144,8 +131,8 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Data Rows */}
|
{/* Data Rows */}
|
||||||
{rows.map((row, rowIndex) => {
|
{data.map((row, rowIndex) => {
|
||||||
const isLastRow = rowIndex === rows.length - 1;
|
const isLastRow = rowIndex === data.length - 1;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
@@ -156,19 +143,27 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{columns.map((column, colIndex) => {
|
{columns.map((column, colIndex) => {
|
||||||
const cell = row.find((c) => c.key === column.key);
|
|
||||||
const isLastColumn = colIndex === columns.length - 1;
|
const isLastColumn = colIndex === columns.length - 1;
|
||||||
const align = cell?.align || column.align || 'center';
|
const align = column.align || 'left';
|
||||||
|
|
||||||
|
// Get cell content from column.cell function or fallback to row value
|
||||||
|
let cellContent: ReactNode;
|
||||||
|
if (column.cell) {
|
||||||
|
cellContent = column.cell({ row, index: rowIndex });
|
||||||
|
} else {
|
||||||
|
cellContent =
|
||||||
|
((row as Record<string, unknown>)[column.key] as ReactNode) ??
|
||||||
|
'-';
|
||||||
|
}
|
||||||
|
|
||||||
const cellStyle =
|
const cellStyle =
|
||||||
column.key === 'no'
|
column.key === 'no'
|
||||||
? [styles.tableCellNo, { flex: column.flex }]
|
? [styles.tableCellNo, { flex: column.flex || 1 }]
|
||||||
: align === 'right'
|
: align === 'right'
|
||||||
? [
|
? [
|
||||||
styles.tableCellRight,
|
styles.tableCellRight,
|
||||||
{
|
{
|
||||||
flex: column.flex,
|
flex: column.flex || 1,
|
||||||
color: cell?.color || 'black',
|
|
||||||
borderRightWidth: isLastColumn ? 0 : 1,
|
borderRightWidth: isLastColumn ? 0 : 1,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@@ -176,37 +171,30 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
|
|||||||
? [
|
? [
|
||||||
styles.tableCellCenter,
|
styles.tableCellCenter,
|
||||||
{
|
{
|
||||||
flex: column.flex,
|
flex: column.flex || 1,
|
||||||
color: cell?.color || 'black',
|
|
||||||
borderRightWidth: isLastColumn ? 0 : 1,
|
borderRightWidth: isLastColumn ? 0 : 1,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
: isLastColumn
|
: isLastColumn
|
||||||
? [
|
? [
|
||||||
styles.tableCellLast,
|
styles.tableCellLast,
|
||||||
{ flex: column.flex, borderRightWidth: 0 },
|
{ flex: column.flex || 1, borderRightWidth: 0 },
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
styles.tableCell,
|
styles.tableCell,
|
||||||
{
|
{
|
||||||
flex: column.flex,
|
flex: column.flex || 1,
|
||||||
color: cell?.color || 'black',
|
|
||||||
borderRightWidth: isLastColumn ? 0 : 1,
|
borderRightWidth: isLastColumn ? 0 : 1,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View key={column.key} style={cellStyle}>
|
<View key={column.key} style={cellStyle}>
|
||||||
{cell?.value !== undefined &&
|
{typeof cellContent === 'string' ||
|
||||||
cell?.value !== null &&
|
typeof cellContent === 'number' ? (
|
||||||
cell?.value !== '' ? (
|
<Text>{String(cellContent)}</Text>
|
||||||
typeof cell.value === 'object' ? (
|
|
||||||
cell.value
|
|
||||||
) : (
|
|
||||||
<Text>{String(cell.value)}</Text>
|
|
||||||
)
|
|
||||||
) : (
|
) : (
|
||||||
<Text>-</Text>
|
cellContent
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@@ -217,3 +205,5 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type { PdfColumn };
|
||||||
|
|||||||
@@ -1,21 +1,8 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Text, View, StyleSheet } from '@react-pdf/renderer';
|
import { Text, View, StyleSheet } from '@react-pdf/renderer';
|
||||||
|
import { ReactNode } from 'react';
|
||||||
export interface PdfColumn {
|
import type { PdfColumn } from './types';
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
tableRow: {
|
tableRow: {
|
||||||
@@ -69,63 +56,86 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface PdfTfootProps {
|
interface PdfTfootProps<TData = Record<string, unknown>> {
|
||||||
columns: PdfColumn[];
|
columns: PdfColumn<TData>[];
|
||||||
cells: PdfTfootCell[];
|
data: TData[];
|
||||||
label?: string;
|
label?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PdfTfoot = ({
|
export const PdfTfoot = <TData = Record<string, unknown>,>({
|
||||||
columns,
|
columns,
|
||||||
cells,
|
data,
|
||||||
label = 'Total',
|
label = 'Total',
|
||||||
}: PdfTfootProps) => {
|
}: PdfTfootProps<TData>) => {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.tableRow, styles.summaryRow]}>
|
<View style={[styles.tableRow, styles.summaryRow]}>
|
||||||
{columns.map((column, index) => {
|
{columns.map((column, index) => {
|
||||||
const isLastColumn = index === columns.length - 1;
|
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 =
|
const cellStyle =
|
||||||
column.key === 'no'
|
column.key === 'no'
|
||||||
? [
|
? [
|
||||||
styles.tableCellNo,
|
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,
|
styles.tableCellRight,
|
||||||
{
|
{
|
||||||
flex: column.flex,
|
flex: column.flex || 1,
|
||||||
color: cellData?.color || 'black',
|
color,
|
||||||
borderRightWidth: isLastColumn ? 0 : 1,
|
borderRightWidth: isLastColumn ? 0 : 1,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
: cellData?.align === 'center'
|
: align === 'center'
|
||||||
? [
|
? [
|
||||||
styles.tableCellCenter,
|
styles.tableCellCenter,
|
||||||
{
|
{
|
||||||
flex: column.flex,
|
flex: column.flex || 1,
|
||||||
color: cellData?.color || 'black',
|
color,
|
||||||
borderRightWidth: isLastColumn ? 0 : 1,
|
borderRightWidth: isLastColumn ? 0 : 1,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
: isLastColumn
|
: isLastColumn
|
||||||
? [styles.tableCellLast, { flex: column.flex }]
|
? [styles.tableCellLast, { flex: column.flex || 1, color }]
|
||||||
: [
|
: [styles.tableCell, { flex: column.flex || 1, color }];
|
||||||
styles.tableCell,
|
|
||||||
{
|
|
||||||
flex: column.flex,
|
|
||||||
color: cellData?.color || 'black',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View key={column.key} style={cellStyle}>
|
<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>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type { PdfColumn };
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Text, View, StyleSheet } from '@react-pdf/renderer';
|
import { Text, View, StyleSheet } from '@react-pdf/renderer';
|
||||||
|
import { ReactNode } from 'react';
|
||||||
export interface PdfColumn {
|
import type { PdfColumn } from './types';
|
||||||
key: string;
|
|
||||||
header: string;
|
|
||||||
flex: number;
|
|
||||||
align?: 'left' | 'center' | 'right';
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
tableRow: {
|
tableRow: {
|
||||||
@@ -48,23 +43,37 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface PdfTheadProps {
|
interface PdfTheadProps<TData = Record<string, unknown>> {
|
||||||
columns: PdfColumn[];
|
columns: PdfColumn<TData>[];
|
||||||
|
data?: TData[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PdfThead = ({ columns }: PdfTheadProps) => {
|
export const PdfThead = <TData = Record<string, unknown>,>({
|
||||||
|
columns,
|
||||||
|
data,
|
||||||
|
}: PdfTheadProps<TData>) => {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.tableRow, styles.tableHeader]}>
|
<View style={[styles.tableRow, styles.tableHeader]}>
|
||||||
{columns.map((column, index) => {
|
{columns.map((column, index) => {
|
||||||
const align = column.align || 'center';
|
|
||||||
const isLastColumn = index === columns.length - 1;
|
const isLastColumn = index === columns.length - 1;
|
||||||
|
|
||||||
|
// Get header content from column definition
|
||||||
|
let headerContent: ReactNode;
|
||||||
|
if (typeof column.header === 'function') {
|
||||||
|
headerContent = column.header(data || []);
|
||||||
|
} else {
|
||||||
|
headerContent = column.header || column.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine alignment - columns align right by default for numeric data
|
||||||
|
const align = column.align || 'left';
|
||||||
|
|
||||||
const cellStyle =
|
const cellStyle =
|
||||||
align === 'right'
|
align === 'right'
|
||||||
? [
|
? [
|
||||||
styles.tableCellHeaderRight,
|
styles.tableCellHeaderRight,
|
||||||
{
|
{
|
||||||
flex: column.flex,
|
flex: column.flex || 1,
|
||||||
textAlign: 'right' as const,
|
textAlign: 'right' as const,
|
||||||
borderRightWidth: isLastColumn ? 0 : 1,
|
borderRightWidth: isLastColumn ? 0 : 1,
|
||||||
},
|
},
|
||||||
@@ -72,7 +81,7 @@ export const PdfThead = ({ columns }: PdfTheadProps) => {
|
|||||||
: [
|
: [
|
||||||
styles.tableCellHeader,
|
styles.tableCellHeader,
|
||||||
{
|
{
|
||||||
flex: column.flex,
|
flex: column.flex || 1,
|
||||||
textAlign: align as 'left' | 'center' | 'right',
|
textAlign: align as 'left' | 'center' | 'right',
|
||||||
borderRightWidth: isLastColumn ? 0 : 1,
|
borderRightWidth: isLastColumn ? 0 : 1,
|
||||||
},
|
},
|
||||||
@@ -80,10 +89,16 @@ export const PdfThead = ({ columns }: PdfTheadProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View key={column.key} style={cellStyle}>
|
<View key={column.key} style={cellStyle}>
|
||||||
<Text>{column.header}</Text>
|
{typeof headerContent === 'string' ? (
|
||||||
|
<Text>{headerContent}</Text>
|
||||||
|
) : (
|
||||||
|
headerContent
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type { PdfColumn };
|
||||||
|
|||||||
@@ -2,6 +2,4 @@ export { PdfTable } from './PdfTable';
|
|||||||
export { PdfThead } from './PdfThead';
|
export { PdfThead } from './PdfThead';
|
||||||
export { PdfTbody } from './PdfTbody';
|
export { PdfTbody } from './PdfTbody';
|
||||||
export { PdfTfoot } from './PdfTfoot';
|
export { PdfTfoot } from './PdfTfoot';
|
||||||
export type { PdfColumn } from './PdfThead';
|
export type { PdfColumn } from './types';
|
||||||
export type { PdfTbodyCell } from './PdfTbody';
|
|
||||||
export type { PdfTfootCell } from './PdfTfoot';
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PdfColumn - Mirip dengan ColumnDef di TanStack Table
|
||||||
|
* Mengatur header (thead), body (tbody), dan footer (tfoot) dalam satu definisi
|
||||||
|
*/
|
||||||
|
export interface PdfColumn<TData = Record<string, unknown>> {
|
||||||
|
key: string;
|
||||||
|
flex?: number;
|
||||||
|
|
||||||
|
// Header configuration (thead)
|
||||||
|
header?: string | ((data: TData[]) => ReactNode);
|
||||||
|
|
||||||
|
// Body configuration (tbody)
|
||||||
|
align?: 'left' | 'center' | 'right';
|
||||||
|
cell?: (props: { row: TData; index: number }) => ReactNode | string | number;
|
||||||
|
|
||||||
|
// Footer configuration (tfoot)
|
||||||
|
footer?: string | number | ((data: TData[]) => ReactNode | string | number);
|
||||||
|
footerAlign?: 'left' | 'center' | 'right';
|
||||||
|
footerColor?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type { PdfColumn as default };
|
||||||
Reference in New Issue
Block a user