mirror of
https://github.com/ershisan99/flashcards-example-project.git
synced 2025-12-24 05:09:29 +00:00
add cards table and pagination
This commit is contained in:
192
src/components/ui/pagination/pagination.tsx
Normal file
192
src/components/ui/pagination/pagination.tsx
Normal file
@@ -0,0 +1,192 @@
|
||||
import { FC } from 'react'
|
||||
|
||||
import { clsx } from 'clsx'
|
||||
|
||||
import s from './pagination.module.scss'
|
||||
import { usePagination } from './usePagination'
|
||||
|
||||
import { KeyboardArrowLeft, KeyboardArrowRight } from '@/assets'
|
||||
|
||||
type PaginationConditionals =
|
||||
| {
|
||||
perPage?: null
|
||||
perPageOptions?: never
|
||||
onPerPageChange?: never
|
||||
}
|
||||
| {
|
||||
perPage: number
|
||||
perPageOptions: number[]
|
||||
onPerPageChange: (itemPerPage: number) => void
|
||||
}
|
||||
|
||||
export type PaginationProps = {
|
||||
count: number
|
||||
page: number
|
||||
onChange: (page: number) => void
|
||||
siblings?: number
|
||||
perPage?: number
|
||||
perPageOptions?: number[]
|
||||
onPerPageChange?: (itemPerPage: number) => void
|
||||
} & PaginationConditionals
|
||||
|
||||
const classNames = {
|
||||
root: s.root,
|
||||
container: s.container,
|
||||
selectBox: s.selectBox,
|
||||
select: s.select,
|
||||
item: s.item,
|
||||
dots: s.dots,
|
||||
icon: s.icon,
|
||||
pageButton(selected?: boolean) {
|
||||
return clsx(this.item, selected && s.selected)
|
||||
},
|
||||
}
|
||||
|
||||
export const Pagination: FC<PaginationProps> = ({
|
||||
onChange,
|
||||
count,
|
||||
page,
|
||||
perPage = null,
|
||||
perPageOptions,
|
||||
onPerPageChange,
|
||||
siblings,
|
||||
}) => {
|
||||
const {
|
||||
paginationRange,
|
||||
isLastPage,
|
||||
isFirstPage,
|
||||
handlePreviousPageClicked,
|
||||
handleNextPageClicked,
|
||||
handleMainPageClicked,
|
||||
} = usePagination({
|
||||
page,
|
||||
count,
|
||||
onChange,
|
||||
siblings,
|
||||
})
|
||||
|
||||
const showPerPageSelect = !!perPage && !!perPageOptions && !!onPerPageChange
|
||||
|
||||
return (
|
||||
<div className={classNames.root}>
|
||||
<div className={classNames.container}>
|
||||
<PrevButton onClick={handlePreviousPageClicked} disabled={isFirstPage} />
|
||||
|
||||
<MainPaginationButtons
|
||||
currentPage={page}
|
||||
onClick={handleMainPageClicked}
|
||||
paginationRange={paginationRange}
|
||||
/>
|
||||
|
||||
<NextButton onClick={handleNextPageClicked} disabled={isLastPage} />
|
||||
</div>
|
||||
|
||||
{showPerPageSelect && (
|
||||
<PerPageSelect
|
||||
{...{
|
||||
perPage,
|
||||
perPageOptions,
|
||||
onPerPageChange,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type NavigationButtonProps = {
|
||||
onClick: () => void
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
type PageButtonProps = NavigationButtonProps & {
|
||||
page: number
|
||||
selected: boolean
|
||||
}
|
||||
|
||||
const Dots: FC = () => {
|
||||
return <span className={classNames.dots}>…</span>
|
||||
}
|
||||
const PageButton: FC<PageButtonProps> = ({ onClick, disabled, selected, page }) => {
|
||||
return (
|
||||
<button
|
||||
onClick={onClick}
|
||||
disabled={selected || disabled}
|
||||
className={classNames.pageButton(selected)}
|
||||
>
|
||||
{page}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
const PrevButton: FC<NavigationButtonProps> = ({ onClick, disabled }) => {
|
||||
return (
|
||||
<button className={classNames.item} onClick={onClick} disabled={disabled}>
|
||||
<KeyboardArrowLeft className={classNames.icon} />
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
const NextButton: FC<NavigationButtonProps> = ({ onClick, disabled }) => {
|
||||
return (
|
||||
<button className={classNames.item} onClick={onClick} disabled={disabled}>
|
||||
<KeyboardArrowRight className={classNames.icon} />
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
type MainPaginationButtonsProps = {
|
||||
paginationRange: (number | string)[]
|
||||
currentPage: number
|
||||
onClick: (pageNumber: number) => () => void
|
||||
}
|
||||
|
||||
const MainPaginationButtons: FC<MainPaginationButtonsProps> = ({
|
||||
paginationRange,
|
||||
currentPage,
|
||||
onClick,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
{paginationRange.map((page: number | string, index) => {
|
||||
const isSelected = page === currentPage
|
||||
|
||||
if (typeof page !== 'number') {
|
||||
return <Dots key={index} />
|
||||
}
|
||||
|
||||
return <PageButton key={index} page={page} selected={isSelected} onClick={onClick(page)} />
|
||||
})}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export type PerPageSelectProps = {
|
||||
perPage: number
|
||||
perPageOptions: number[]
|
||||
onPerPageChange: (itemPerPage: number) => void
|
||||
}
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user