chore: update Table component

This commit is contained in:
ValdiANS
2025-12-04 23:09:08 +07:00
parent be725d42c3
commit bac3f30ce3
+59 -29
View File
@@ -38,6 +38,7 @@ export interface TableProps<TData extends object> {
data: TData[]; data: TData[];
columns: ColumnDef<TData, unknown>[]; columns: ColumnDef<TData, unknown>[];
pageSize?: number; pageSize?: number;
onPageSizeChange?: (pageSize: number) => void;
totalItems?: number; totalItems?: number;
page?: number; page?: number;
onPageChange?: (page: number) => void; onPageChange?: (page: number) => void;
@@ -52,6 +53,8 @@ export interface TableProps<TData extends object> {
rowSelection?: Record<string, boolean>; rowSelection?: Record<string, boolean>;
setRowSelection?: OnChangeFn<Record<string, boolean>>; setRowSelection?: OnChangeFn<Record<string, boolean>>;
enableRowSelection?: boolean | ((row: Row<TData>) => boolean); enableRowSelection?: boolean | ((row: Row<TData>) => boolean);
withCheckbox?: boolean;
rowOptions?: number[];
} }
const DUMMY_SKELETON_DATA = [{}, {}, {}, {}, {}]; const DUMMY_SKELETON_DATA = [{}, {}, {}, {}, {}];
@@ -64,28 +67,32 @@ const emptyContentDefaultValue = (
</div> </div>
); );
const TABLE_DEFAULT_STYLING = {
containerClassName: 'w-full mb-20',
tableWrapperClassName:
'overflow-x-auto border border-solid border-base-content/10 rounded-lg',
tableClassName: 'font-inter w-full table-auto text-sm font-medium',
tableHeaderClassName: '',
headerRowClassName: '',
headerColumnClassName: 'px-4 py-3 text-base-content/50',
tableBodyClassName: '',
bodyRowClassName: 'border-t border-t-base-content/10',
bodyColumnClassName: 'px-4 py-3 text-base-content',
paginationClassName: '',
};
const Table = <TData extends object>({ const Table = <TData extends object>({
data = [], data = [],
columns = [], columns = [],
pageSize = 10, pageSize = 10,
onPageSizeChange,
totalItems, totalItems,
page, page,
onPageChange, onPageChange,
isLoading = false, isLoading = false,
fuzzySearchValue, fuzzySearchValue,
onFuzzySearchValueChange, onFuzzySearchValueChange,
className = { className = TABLE_DEFAULT_STYLING,
containerClassName: '',
tableWrapperClassName: '',
tableClassName: '',
tableHeaderClassName: '',
headerRowClassName: '',
headerColumnClassName: '',
tableBodyClassName: '',
bodyRowClassName: '',
bodyColumnClassName: '',
paginationClassName: '',
},
emptyContent = emptyContentDefaultValue, emptyContent = emptyContentDefaultValue,
sorting, sorting,
setSorting, setSorting,
@@ -93,12 +100,19 @@ const Table = <TData extends object>({
rowSelection, rowSelection,
setRowSelection, setRowSelection,
enableRowSelection, enableRowSelection,
withCheckbox = false,
rowOptions = [10, 20, 50, 100],
}: TableProps<TData>) => { }: TableProps<TData>) => {
const isServerSideTable = const isServerSideTable =
totalItems !== undefined && totalItems !== undefined &&
page !== undefined && page !== undefined &&
onPageChange !== undefined; onPageChange !== undefined;
const tableClassNames = {
...TABLE_DEFAULT_STYLING,
...className,
};
const [pagination, setPagination] = useState({ const [pagination, setPagination] = useState({
pageIndex: 0, pageIndex: 0,
pageSize: pageSize, pageSize: pageSize,
@@ -191,12 +205,15 @@ const Table = <TData extends object>({
}, [pageSize, setPageSize]); }, [pageSize, setPageSize]);
return ( return (
<div className={className.containerClassName}> <div className={tableClassNames.containerClassName}>
<div className={className.tableWrapperClassName}> <div className={tableClassNames.tableWrapperClassName}>
<table className={className.tableClassName}> <table className={tableClassNames.tableClassName}>
<thead className={className.tableHeaderClassName}> <thead className={tableClassNames.tableHeaderClassName}>
{table.getHeaderGroups().map((headerGroup) => ( {table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id} className={className.headerRowClassName}> <tr
key={headerGroup.id}
className={tableClassNames.headerRowClassName}
>
{headerGroup.headers.map((header) => ( {headerGroup.headers.map((header) => (
<th <th
key={header.id} key={header.id}
@@ -206,7 +223,10 @@ const Table = <TData extends object>({
header.column.getCanSort() header.column.getCanSort()
? 'cursor-pointer select-none' ? 'cursor-pointer select-none'
: '', : '',
className.headerColumnClassName {
'first:w-9 first:pr-0': withCheckbox,
},
tableClassNames.headerColumnClassName
)} )}
> >
<div className='flex items-center gap-1'> <div className='flex items-center gap-1'>
@@ -216,12 +236,13 @@ const Table = <TData extends object>({
)} )}
{header.column.getCanSort() && ( {header.column.getCanSort() && (
<div className='flex items-center'> <div className='w-4 h-4 relative flex flex-col items-center'>
<Icon <Icon
icon='lucide:arrow-up' icon='heroicons:chevron-up-16-solid'
width={12} width={18}
height={12} height={18}
className={cn( className={cn(
'absolute -top-1',
'transition-all ease-in-out duration-200', 'transition-all ease-in-out duration-200',
header.column.getIsSorted() === 'asc' header.column.getIsSorted() === 'asc'
? 'text-black' ? 'text-black'
@@ -229,10 +250,11 @@ const Table = <TData extends object>({
)} )}
/> />
<Icon <Icon
icon='lucide:arrow-down' icon='heroicons:chevron-down-16-solid'
width={12} width={18}
height={12} height={18}
className={cn( className={cn(
'absolute -bottom-1.5',
'transition-all ease-in-out duration-200', 'transition-all ease-in-out duration-200',
header.column.getIsSorted() === 'desc' header.column.getIsSorted() === 'desc'
? 'text-black' ? 'text-black'
@@ -248,11 +270,17 @@ const Table = <TData extends object>({
))} ))}
</thead> </thead>
<tbody className={className.tableBodyClassName}> <tbody className={tableClassNames.tableBodyClassName}>
{table.getRowModel().rows.map((row) => ( {table.getRowModel().rows.map((row) => (
<tr key={row.id} className={className.bodyRowClassName}> <tr key={row.id} className={tableClassNames.bodyRowClassName}>
{row.getVisibleCells().map((cell) => ( {row.getVisibleCells().map((cell) => (
<td key={cell.id} className={className.bodyColumnClassName}> <td
key={cell.id}
className={cn(
{ 'first:w-9 first:pr-0': withCheckbox },
tableClassNames.bodyColumnClassName
)}
>
{!isLoading && {!isLoading &&
flexRender(cell.column.columnDef.cell, cell.getContext())} flexRender(cell.column.columnDef.cell, cell.getContext())}
@@ -270,7 +298,7 @@ const Table = <TData extends object>({
emptyContent} emptyContent}
{data.length > 0 && table.getRowModel().rows.length > 0 && !isLoading && ( {data.length > 0 && table.getRowModel().rows.length > 0 && !isLoading && (
<div className={cn('mt-5', className.paginationClassName)}> <div className={cn('mt-5', tableClassNames.paginationClassName)}>
<Pagination <Pagination
totalItems={isServerSideTable ? totalItems : table.getRowCount()} totalItems={isServerSideTable ? totalItems : table.getRowCount()}
itemsPerPage={table.getState().pagination.pageSize} itemsPerPage={table.getState().pagination.pageSize}
@@ -282,6 +310,8 @@ const Table = <TData extends object>({
onPrevPage={prevPageClickHandler} onPrevPage={prevPageClickHandler}
onNextPage={nextPageClickHandler} onNextPage={nextPageClickHandler}
onPageChange={pageChangeHandler} onPageChange={pageChangeHandler}
rowOptions={rowOptions}
onRowChange={onPageSizeChange}
/> />
</div> </div>
)} )}