feat: add pagination table

This commit is contained in:
Paul Pan 2024-03-15 23:26:18 +08:00
parent 9dfe9bfe81
commit 43f5423cf9
3 changed files with 157 additions and 0 deletions

View File

@ -22,6 +22,7 @@
"@emotion/react": "^11.11.4", "@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.11.0",
"@reduxjs/toolkit": "^2.2.1", "@reduxjs/toolkit": "^2.2.1",
"@tanstack/react-table": "^8.13.2",
"ace-builds": "^1.32.7", "ace-builds": "^1.32.7",
"framer-motion": "^11.0.13", "framer-motion": "^11.0.13",
"github-markdown-css": "^5.5.1", "github-markdown-css": "^5.5.1",

View File

@ -26,6 +26,9 @@ dependencies:
'@reduxjs/toolkit': '@reduxjs/toolkit':
specifier: ^2.2.1 specifier: ^2.2.1
version: 2.2.1(react-redux@9.1.0)(react@18.2.0) 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: ace-builds:
specifier: ^1.32.7 specifier: ^1.32.7
version: 1.32.7 version: 1.32.7
@ -2374,6 +2377,23 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dev: false 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: /@types/babel__core@7.20.5:
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
dependencies: dependencies:

136
src/components/Table.tsx Normal file
View 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>
</>
);
}