diff --git a/package.json b/package.json index b7b7244..bc46e94 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 084193e..3d374ee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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: diff --git a/src/components/Table.tsx b/src/components/Table.tsx new file mode 100644 index 0000000..8299f39 --- /dev/null +++ b/src/components/Table.tsx @@ -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 { + data: T[]; + columns: ColumnDef[]; + total: number; + paging: PaginationState; + setPaging: (state: PaginationState | ((old: PaginationState) => PaginationState)) => void; + isLoading: boolean; +} + +export default function Table(props: TableProps) { + 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 ( + <> + + + + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + + {header.isPlaceholder + ? null + : flexRender(header.column.columnDef.header, header.getContext())} + + + ))} + + ))} + + + {table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + ))} + + + + + } + onClick={() => table.firstPage()} + isDisabled={!table.getCanPreviousPage()} + /> + } + onClick={() => table.previousPage()} + isDisabled={!table.getCanPreviousPage()} + /> + + + + Page {pageIndex + 1} of {pageCount} + + + + + } + onClick={() => table.nextPage()} + isDisabled={!table.getCanNextPage()} + /> + } + onClick={() => table.lastPage()} + isDisabled={!table.getCanNextPage()} + /> + + + + + + ); +}