Files
flashcards-example-project/src/components/ui/pagination/pagination.tsx
2023-11-18 16:34:09 +01:00

201 lines
4.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { FC } from 'react'
import { usePagination } from './usePagination'
import { KeyboardArrowLeft, KeyboardArrowRight } from '@/assets'
import { clsx } from 'clsx'
import s from './pagination.module.scss'
type PaginationConditionals =
| {
onPerPageChange: (itemPerPage: number) => void
perPage: number
perPageOptions: number[]
}
| {
onPerPageChange?: never
perPage?: null
perPageOptions?: never
}
export type PaginationProps = {
count: number
onChange: (page: number) => void
onPerPageChange?: (itemPerPage: number) => void
page: number
perPage?: number
perPageOptions?: number[]
siblings?: number
} & PaginationConditionals
const classNames = {
container: s.container,
dots: s.dots,
icon: s.icon,
item: s.item,
pageButton(selected?: boolean) {
return clsx(this.item, selected && s.selected)
},
root: s.root,
select: s.select,
selectBox: s.selectBox,
}
export const Pagination: FC<PaginationProps> = ({
count,
onChange,
onPerPageChange,
page,
perPage = null,
perPageOptions,
siblings,
}) => {
const {
handleMainPageClicked,
handleNextPageClicked,
handlePreviousPageClicked,
isFirstPage,
isLastPage,
paginationRange,
} = usePagination({
count,
onChange,
page,
siblings,
})
const showPerPageSelect = !!perPage && !!perPageOptions && !!onPerPageChange
return (
<div className={classNames.root}>
<div className={classNames.container}>
<PrevButton disabled={isFirstPage} onClick={handlePreviousPageClicked} />
<MainPaginationButtons
currentPage={page}
onClick={handleMainPageClicked}
paginationRange={paginationRange}
/>
<NextButton disabled={isLastPage} onClick={handleNextPageClicked} />
</div>
{showPerPageSelect && (
<PerPageSelect
{...{
onPerPageChange,
perPage,
perPageOptions,
}}
/>
)}
</div>
)
}
type NavigationButtonProps = {
disabled?: boolean
onClick: () => void
}
type PageButtonProps = NavigationButtonProps & {
page: number
selected: boolean
}
const Dots: FC = () => {
return <span className={classNames.dots}>&#8230;</span>
}
const PageButton: FC<PageButtonProps> = ({ disabled, onClick, page, selected }) => {
return (
<button
className={classNames.pageButton(selected)}
disabled={selected || disabled}
onClick={onClick}
>
{page}
</button>
)
}
const PrevButton: FC<NavigationButtonProps> = ({ disabled, onClick }) => {
return (
<button className={classNames.item} disabled={disabled} onClick={onClick}>
<KeyboardArrowLeft className={classNames.icon} />
</button>
)
}
const NextButton: FC<NavigationButtonProps> = ({ disabled, onClick }) => {
return (
<button className={classNames.item} disabled={disabled} onClick={onClick}>
<KeyboardArrowRight className={classNames.icon} />
</button>
)
}
type MainPaginationButtonsProps = {
currentPage: number
onClick: (pageNumber: number) => () => void
paginationRange: (number | string)[]
}
const MainPaginationButtons: FC<MainPaginationButtonsProps> = ({
currentPage,
onClick,
paginationRange,
}) => {
return (
<>
{paginationRange.map((page: number | string, index) => {
const isSelected = page === currentPage
if (typeof page !== 'number') {
return <Dots key={index} />
}
return (
<PageButton
key={index}
onClick={onClick(page)}
page={page}
selected={isSelected}
/>
)
})}
</>
)
}
export type PerPageSelectProps = {
onPerPageChange: (itemPerPage: number) => void
perPage: number
perPageOptions: number[]
}
export const PerPageSelect: FC<PerPageSelectProps> = (
{
// perPage,
// perPageOptions,
// onPerPageChange,
}
) => {
// const selectOptions = perPageOptions.map(value => ({
// label: value,
// value,
// }))
return (
<div className={classNames.selectBox}>
Показать
{/*<Select*/}
{/* className={classNames.select}*/}
{/* value={perPage}*/}
{/* options={selectOptions}*/}
{/* onChange={onPerPageChange}*/}
{/* variant="pagination"*/}
{/*/>*/}
на странице
</div>
)
}