Skip to content

Instantly share code, notes, and snippets.

@mnzsss
Last active October 6, 2021 19:03
Show Gist options
  • Save mnzsss/f2e54aa22c591148a5bb6af95673d10a to your computer and use it in GitHub Desktop.
Save mnzsss/f2e54aa22c591148a5bb6af95673d10a to your computer and use it in GitHub Desktop.
/* eslint-disable indent */
import { Stack, Text } from '@chakra-ui/react'
import { PaginationItem } from './PaginationItem'
type PaginationProps = {
onPageChange: (page: number) => void
currentPage: number
lastPage: number
nextPages: number[]
previousPages: number[]
siblingsCount: number
}
export function Pagination({
currentPage,
lastPage,
previousPages,
nextPages,
siblingsCount,
onPageChange
}: PaginationProps) {
return (
<Stack direction="row" mt="8" justify="flex-end" align="center" spacing="6">
<Stack direction="row" spacing="4">
{currentPage > 1 + siblingsCount ? (
<>
<PaginationItem onPageChange={onPageChange} page={1} />
{currentPage > 2 + siblingsCount ? (
<Text color="gray.300" w="8" textAlign="center">
...
</Text>
) : null}
</>
) : null}
{previousPages.length > 0
? previousPages.map(page => (
<PaginationItem
onPageChange={onPageChange}
page={page}
key={page}
/>
))
: null}
<PaginationItem
onPageChange={onPageChange}
page={currentPage}
isCurrent
/>
{nextPages.length > 0
? nextPages.map(page => (
<PaginationItem
onPageChange={onPageChange}
page={page}
key={page}
/>
))
: null}
{currentPage + siblingsCount < lastPage ? (
<>
{currentPage + 1 + siblingsCount < lastPage ? (
<Text color="gray.300" w="8" textAlign="center">
...
</Text>
) : null}
<PaginationItem onPageChange={onPageChange} page={lastPage} />
</>
) : null}
</Stack>
</Stack>
)
}
import { Button } from '@chakra-ui/react'
type PaginationItemProps = {
isCurrent?: boolean
page: number
onPageChange: (page: number) => void
}
export function PaginationItem({
isCurrent = false,
page,
onPageChange
}: PaginationItemProps) {
if (isCurrent) {
return (
<Button
size="sm"
fontSize="xs"
width="4"
colorScheme="teal"
disabled
_disabled={{
bg: 'teal.500',
cursor: 'pointer'
}}
>
{page}
</Button>
)
}
return (
<Button
size="sm"
fontSize="xs"
width="4"
bg="gray.100"
_hover={{
bg: 'gray.300'
}}
onClick={() => onPageChange(page)}
>
{page}
</Button>
)
}
import {
Table as ChakraTable,
Thead,
Tbody,
Tr,
Th,
Td,
Box
} from '@chakra-ui/react'
import { usePagination } from '@hooks/usePagination'
import { Fragment } from 'react'
import { Column, useTable } from 'react-table'
import { Pagination } from './Pagination'
interface TableProps {
columns: Array<Column>
data: any[]
page: number
totalRegisters: number
onPageChange: (page: number) => void
noShadow?: boolean
}
export function Table({
page,
onPageChange,
totalRegisters,
data = [],
columns = [],
noShadow = false
}: TableProps) {
const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } =
useTable({ columns, data })
const pagination = usePagination({
totalRegisters,
page
})
return (
<Box
py="6"
px="8"
borderRadius="8"
boxShadow={noShadow ? 'unset' : 'md'}
w="full"
h="100%"
>
<ChakraTable {...getTableProps()}>
<Thead>
{headerGroups.map(headerGroup => (
<Tr {...headerGroup.getHeaderGroupProps()} key={headerGroup.id}>
{headerGroup.headers.map(column => (
<Fragment key={column.id}>
<Th {...column.getHeaderProps()}>
{column.render('Header')}
</Th>
</Fragment>
))}
</Tr>
))}
</Thead>
<Tbody {...getTableBodyProps()}>
{rows.map(row => {
prepareRow(row)
return (
<Tr {...row.getRowProps()} key={row.id}>
{row.cells.map((cell, index) => (
<Fragment key={cell.column.id + index}>
<Td {...cell.getCellProps()}>{cell.render('Cell')}</Td>
</Fragment>
))}
</Tr>
)
})}
</Tbody>
</ChakraTable>
<Pagination {...pagination} onPageChange={onPageChange} />
</Box>
)
}
/* eslint-disable indent */
type Options = {
totalRegisters: number
page: number
}
type Pagination = {
totalPages: number
registersPerPage: number
currentPage: number
lastPage: number
nextPages: number[]
previousPages: number[]
siblingsCount: number
}
// Default Values
const SIBLINGS_COUNT = 1
const REGISTERS_PER_PAGE = 10
function generatePagesArray(from: number, to: number): number[] {
return [...new Array(to - from)]
.map((_, index) => from + index + 1)
.filter(page => page > 0)
}
export function usePagination({ totalRegisters, page }: Options): Pagination {
const currentPage = page
const lastPage = Math.ceil(totalRegisters / REGISTERS_PER_PAGE)
const totalPages = lastPage === 0 ? 1 : lastPage
const previousPages =
currentPage > 1
? generatePagesArray(currentPage - 1 - SIBLINGS_COUNT, currentPage - 1)
: []
const nextPages =
currentPage < lastPage
? generatePagesArray(
currentPage,
Math.min(currentPage + SIBLINGS_COUNT, lastPage)
)
: []
return {
currentPage,
totalPages,
lastPage,
nextPages,
previousPages,
registersPerPage: REGISTERS_PER_PAGE,
siblingsCount: SIBLINGS_COUNT
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment