feat: add pagination table
This commit is contained in:
parent
9dfe9bfe81
commit
43f5423cf9
@ -22,6 +22,7 @@
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@reduxjs/toolkit": "^2.2.1",
|
||||
"@tanstack/react-table": "^8.13.2",
|
||||
"ace-builds": "^1.32.7",
|
||||
"framer-motion": "^11.0.13",
|
||||
"github-markdown-css": "^5.5.1",
|
||||
|
@ -26,6 +26,9 @@ dependencies:
|
||||
'@reduxjs/toolkit':
|
||||
specifier: ^2.2.1
|
||||
version: 2.2.1(react-redux@9.1.0)(react@18.2.0)
|
||||
'@tanstack/react-table':
|
||||
specifier: ^8.13.2
|
||||
version: 8.13.2(react-dom@18.2.0)(react@18.2.0)
|
||||
ace-builds:
|
||||
specifier: ^1.32.7
|
||||
version: 1.32.7
|
||||
@ -2374,6 +2377,23 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/@tanstack/react-table@8.13.2(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-b6mR3mYkjRtJ443QZh9sc7CvGTce81J35F/XMr0OoWbx0KIM7TTTdyNP2XKObvkLpYnLpCrYDwI3CZnLezWvpg==}
|
||||
engines: {node: '>=12'}
|
||||
peerDependencies:
|
||||
react: '>=16'
|
||||
react-dom: '>=16'
|
||||
dependencies:
|
||||
'@tanstack/table-core': 8.13.2
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@tanstack/table-core@8.13.2:
|
||||
resolution: {integrity: sha512-/2saD1lWBUV6/uNAwrsg2tw58uvMJ07bO2F1IWMxjFRkJiXKQRuc3Oq2aufeobD3873+4oIM/DRySIw7+QsPPw==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/@types/babel__core@7.20.5:
|
||||
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
|
||||
dependencies:
|
||||
|
136
src/components/Table.tsx
Normal file
136
src/components/Table.tsx
Normal file
@ -0,0 +1,136 @@
|
||||
import {
|
||||
Card,
|
||||
CardFooter,
|
||||
Flex,
|
||||
IconButton,
|
||||
Select,
|
||||
SkeletonText,
|
||||
Table as ChakraTable,
|
||||
Tbody,
|
||||
Td,
|
||||
Text,
|
||||
Th,
|
||||
Thead,
|
||||
Tr,
|
||||
useColorModeValue,
|
||||
} from "@chakra-ui/react";
|
||||
import type { ColumnDef, PaginationState } from "@tanstack/react-table";
|
||||
import { flexRender, getCoreRowModel, getFilteredRowModel, useReactTable } from "@tanstack/react-table";
|
||||
import { HiChevronDoubleLeft, HiChevronDoubleRight, HiChevronLeft, HiChevronRight } from "react-icons/hi";
|
||||
|
||||
interface TableProps<T> {
|
||||
data: T[];
|
||||
columns: ColumnDef<T>[];
|
||||
total: number;
|
||||
paging: PaginationState;
|
||||
setPaging: (state: PaginationState | ((old: PaginationState) => PaginationState)) => void;
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
export default function Table<T>(props: TableProps<T>) {
|
||||
const bg = useColorModeValue("gray.100", "gray.900");
|
||||
|
||||
const table = useReactTable({
|
||||
data: props.data,
|
||||
columns: props.columns,
|
||||
rowCount: props.total,
|
||||
state: { pagination: props.paging },
|
||||
onPaginationChange: props.setPaging,
|
||||
manualPagination: true,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
debugTable: true,
|
||||
});
|
||||
|
||||
const { pageSize, pageIndex } = table.getState().pagination;
|
||||
const pageCount = table.getPageCount().toLocaleString();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card flexDirection="column" flex={1} maxWidth="100%" width="100%">
|
||||
<SkeletonText noOfLines={6} spacing="4" skeletonHeight="3" isLoaded={!props.isLoading}>
|
||||
<ChakraTable>
|
||||
<Thead>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<Tr key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header) => (
|
||||
<Th key={header.id} colSpan={header.colSpan} bg={bg} py={4} px={6}>
|
||||
<Text fontWeight="bold">
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(header.column.columnDef.header, header.getContext())}
|
||||
</Text>
|
||||
</Th>
|
||||
))}
|
||||
</Tr>
|
||||
))}
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{table.getRowModel().rows.map((row) => (
|
||||
<Tr key={row.id}>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<Td key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</Td>
|
||||
))}
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</ChakraTable>
|
||||
<CardFooter justify="space-between" alignItems="center" overflow="hidden" p={3}>
|
||||
<Flex flexDirection="row">
|
||||
<IconButton
|
||||
aria-label="goto to first page"
|
||||
size="sm"
|
||||
ml={4}
|
||||
mr={2}
|
||||
icon={<HiChevronDoubleLeft size={20} />}
|
||||
onClick={() => table.firstPage()}
|
||||
isDisabled={!table.getCanPreviousPage()}
|
||||
/>
|
||||
<IconButton
|
||||
aria-label="go to previous page"
|
||||
size="sm"
|
||||
mr={2}
|
||||
icon={<HiChevronLeft size={20} />}
|
||||
onClick={() => table.previousPage()}
|
||||
isDisabled={!table.getCanPreviousPage()}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex justifyContent="center" alignItems="center">
|
||||
<Text mr={4}>
|
||||
Page {pageIndex + 1} of {pageCount}
|
||||
</Text>
|
||||
<Select w={28} value={pageSize} onChange={(e) => table.setPageSize(Number(e.target.value))}>
|
||||
{[5, 10, 15, 20].map((pageSize) => (
|
||||
<option key={pageSize} value={pageSize}>
|
||||
Show {pageSize}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
</Flex>
|
||||
<Flex flexDirection="row">
|
||||
<IconButton
|
||||
aria-label="go to next page"
|
||||
size="sm"
|
||||
ml={2}
|
||||
icon={<HiChevronRight size={20} />}
|
||||
onClick={() => table.nextPage()}
|
||||
isDisabled={!table.getCanNextPage()}
|
||||
/>
|
||||
<IconButton
|
||||
aria-label="go to last page"
|
||||
size="sm"
|
||||
ml={2}
|
||||
mr={4}
|
||||
icon={<HiChevronDoubleRight size={20} />}
|
||||
onClick={() => table.lastPage()}
|
||||
isDisabled={!table.getCanNextPage()}
|
||||
/>
|
||||
</Flex>
|
||||
</CardFooter>
|
||||
</SkeletonText>
|
||||
</Card>
|
||||
</>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user