181 lines
5.5 KiB
TypeScript
181 lines
5.5 KiB
TypeScript
import React, { useState } from 'react';
|
|
import {
|
|
createColumnHelper,
|
|
flexRender,
|
|
getCoreRowModel,
|
|
useReactTable,
|
|
getPaginationRowModel,
|
|
getSortedRowModel,
|
|
getFilteredRowModel,
|
|
FilterFn,
|
|
} from '@tanstack/react-table';
|
|
|
|
interface CodeInfo { email: string; name: string; passport_id: string }
|
|
|
|
const globalFilterFn: FilterFn<any> = (row, columnId, filterValue: string) => {
|
|
const value = row.getValue(columnId);
|
|
return String(value).toLowerCase().includes(filterValue.toLowerCase());
|
|
};
|
|
|
|
const columnHelper = createColumnHelper<CodeInfo>();
|
|
|
|
const columns = [
|
|
columnHelper.accessor('name', {
|
|
cell: info => info.getValue(),
|
|
header: () => 'Name',
|
|
}),
|
|
columnHelper.accessor('passport_id', {
|
|
cell: info => info.getValue(),
|
|
header: () => 'Passport/National ID',
|
|
}),
|
|
columnHelper.accessor('email', {
|
|
cell: info => info.getValue(),
|
|
header: () => 'E-mail',
|
|
}),
|
|
];
|
|
|
|
|
|
const CodegenTable: React.FC<{ infos: CodeInfo[]; }> = ({ infos }) => {
|
|
const [globalFilter, setGlobalFilter] = useState('');
|
|
|
|
const table = useReactTable({
|
|
data: infos,
|
|
columns,
|
|
getCoreRowModel: getCoreRowModel(),
|
|
getPaginationRowModel: getPaginationRowModel(),
|
|
getSortedRowModel: getSortedRowModel(),
|
|
getFilteredRowModel: getFilteredRowModel(),
|
|
globalFilterFn: globalFilterFn,
|
|
state: {
|
|
globalFilter,
|
|
},
|
|
onGlobalFilterChange: setGlobalFilter,
|
|
initialState: {
|
|
pagination: {
|
|
pageSize: 5,
|
|
},
|
|
}
|
|
});
|
|
|
|
return (
|
|
<div className='flex flex-col'>
|
|
<div className="flex flew-row w-full mb-4 justify-between gap-4">
|
|
<input
|
|
type="text"
|
|
value={globalFilter ?? ''}
|
|
onChange={e => setGlobalFilter(e.target.value)}
|
|
placeholder="Search ..."
|
|
className="p-2 border rounded flex-grow"
|
|
/>
|
|
<select
|
|
value={table.getState().pagination.pageSize}
|
|
onChange={e => {
|
|
table.setPageSize(Number(e.target.value));
|
|
}}
|
|
className="p-2 border rounded"
|
|
>
|
|
{[5, 10, 15, 20].map(pageSize => (
|
|
<option key={pageSize} value={pageSize}>
|
|
Show {pageSize}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
<table className="w-full">
|
|
<thead>
|
|
{table.getHeaderGroups().map(headerGroup => (
|
|
<tr key={headerGroup.id}>
|
|
{headerGroup.headers.map(header => (
|
|
<th
|
|
key={header.id}
|
|
className='bg-mti-purple-ultralight/80 first:rounded-tl-3xl last:rounded-tr-3xl py-4 first:pl-6 text-mti-purple-light cursor-pointer'
|
|
onClick={header.column.getToggleSortingHandler()}
|
|
>
|
|
{header.isPlaceholder ? null : (
|
|
<div className='flex flex-row justify-between'>
|
|
<span>
|
|
{flexRender(
|
|
header.column.columnDef.header,
|
|
header.getContext()
|
|
)}
|
|
</span>
|
|
<span className='pr-6'>
|
|
{{
|
|
asc: ' 🔼',
|
|
desc: ' 🔽',
|
|
}[header.column.getIsSorted() as string] ?? null}
|
|
</span>
|
|
</div>
|
|
)}
|
|
</th>
|
|
))}
|
|
</tr>
|
|
))}
|
|
</thead>
|
|
<tbody>
|
|
{table.getRowModel().rows.map((row, index, array) => {
|
|
const isLastRow = index === array.length - 1;
|
|
return (
|
|
<tr key={row.id}>
|
|
{row.getVisibleCells().map((cell) => {
|
|
return (
|
|
<td
|
|
key={cell.id}
|
|
className={
|
|
isLastRow
|
|
? `first:rounded-bl-3xl last:rounded-br-3xl py-4 first:pl-6 bg-mti-purple-ultralight/40`
|
|
: `first:pl-6 py-4 border-b bg-mti-purple-ultralight/40`
|
|
}
|
|
>
|
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
</td>
|
|
);
|
|
})}
|
|
</tr>
|
|
);
|
|
})}
|
|
</tbody>
|
|
</table>
|
|
<div className="mt-4 flex items-center gap-4 mx-auto">
|
|
<button
|
|
onClick={() => table.setPageIndex(0)}
|
|
disabled={!table.getCanPreviousPage()}
|
|
className="px-4 py-2 bg-mti-purple-light text-white rounded disabled:opacity-50"
|
|
>
|
|
{'<<'}
|
|
</button>
|
|
<button
|
|
onClick={() => table.previousPage()}
|
|
disabled={!table.getCanPreviousPage()}
|
|
className="px-4 py-2 bg-mti-purple-light text-white rounded disabled:opacity-50"
|
|
>
|
|
{'<'}
|
|
</button>
|
|
<span>
|
|
Page{' '}
|
|
<strong>
|
|
{table.getState().pagination.pageIndex + 1} of{' '}
|
|
{table.getPageCount()}
|
|
</strong>
|
|
</span>
|
|
<button
|
|
onClick={() => table.nextPage()}
|
|
disabled={!table.getCanNextPage()}
|
|
className="px-4 py-2 bg-mti-purple-light text-white rounded disabled:opacity-50"
|
|
>
|
|
{'>'}
|
|
</button>
|
|
<button
|
|
onClick={() => table.setPageIndex(table.getPageCount() - 1)}
|
|
disabled={!table.getCanNextPage()}
|
|
className="px-4 py-2 bg-mti-purple-light text-white rounded disabled:opacity-50"
|
|
>
|
|
{'>>'}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default CodegenTable;
|