muryshev's picture
init
79278ec
import { FC, useCallback, useMemo, useState } from "react";
import { GoChevronLeft, GoChevronRight } from "react-icons/go";
import Select from "react-select";
import Button from "@/components/generics/button/Button";
import { PaginationType } from "@/api/documents/types";
import "./Pagination.scss";
import Input from "@/components/generics/input/Input";
interface PageSizeOption {
value: number;
label: string;
}
export type PaginationProps = PaginationType & {
setPage: React.Dispatch<React.SetStateAction<number>>;
setPageSize: React.Dispatch<React.SetStateAction<number>>;
};
const pageSizeOptions: PageSizeOption[] = [
{ value: 10, label: "10 / стр." },
{ value: 20, label: "20 / стр." },
{ value: 50, label: "50 / стр." },
{ value: 100, label: "100 / стр." },
];
export const Pagination: FC<PaginationProps> = ({ total, pageNumber, pageSize, setPage, setPageSize }) => {
const [searchPage, setSearchPage] = useState<string | null>(null);
const totalPages = Math.ceil(total / pageSize);
const handleChange = useCallback(
(page: number) => {
setPage(page);
},
[setPage]
);
const handlePageSizeChange = (selectedOption: PageSizeOption | null) => {
if (selectedOption) {
setPageSize(selectedOption.value);
setPage(0);
}
};
const pages = useMemo(() => {
let startPage = 1;
let endPage = totalPages;
if (totalPages > 5) {
if (pageNumber + 1 <= 3) {
endPage = 5;
} else if (pageNumber + 3 >= totalPages) {
startPage = totalPages - 4;
} else {
startPage = pageNumber - 1;
endPage = pageNumber + 3;
}
}
const pageNumbers = [];
if (startPage > 1) {
pageNumbers.push(
<Button
key={1}
name={`${1}`}
onClick={() => {
handleChange(0);
}}
className={`item ${pageNumber + 1 === 1 ? "active" : ""}`}
/>
);
if (startPage > 2) {
pageNumbers.push(<span key="ellipsis-start">...</span>);
}
}
for (let i = startPage; i <= endPage; i++) {
pageNumbers.push(
<Button
key={i}
name={`${i}`}
onClick={() => {
handleChange(i - 1);
}}
className={`item ${pageNumber + 1 === i ? "active" : ""}`}
/>
);
}
if (endPage < totalPages) {
if (endPage < totalPages - 1) {
pageNumbers.push(<span key="ellipsis-end">...</span>);
}
pageNumbers.push(
<Button
key={totalPages}
name={`${totalPages}`}
onClick={() => {
handleChange(totalPages - 1);
}}
className={`item ${pageNumber + 1 === totalPages ? "active" : ""}`}
/>
);
}
return pageNumbers;
}, [handleChange, pageNumber, totalPages]);
const handleEnterPress = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === "Enter" && searchPage) {
const pageNumberToGo = Number(searchPage);
if (pageNumberToGo >= 1 && pageNumberToGo <= totalPages) {
setPage(pageNumberToGo - 1);
}
}
};
return (
<div className="pagination">
<Button
onClick={() => {
handleChange(pageNumber - 1);
}}
icon={<GoChevronLeft />}
buttonType="link"
disabled={pageNumber === 0}
/>
{pages}
<Button
onClick={() => {
handleChange(pageNumber + 1);
}}
icon={<GoChevronRight />}
buttonType="link"
disabled={pageNumber === totalPages - 1}
/>
<div className="page-actions">
<Input
name=""
type="number"
max={totalPages.toString()}
min="0"
step="1"
placeholder="Номер страницы"
value={searchPage?.toString()}
onSetValue={(value) => setSearchPage(value)}
onKeyDown={handleEnterPress}
extra={
<Button
disabled={!searchPage}
icon={<GoChevronRight style={{ width: "18px", height: "18px" }} />}
onClick={() => (Number(searchPage) && Number(searchPage) >= 1 ? setPage(Number(searchPage) - 1) : null)}
buttonType="link"
/>
}
/>
<Select
options={pageSizeOptions}
value={pageSizeOptions.find((option) => option.value === pageSize)}
onChange={handlePageSizeChange}
isSearchable={false}
classNamePrefix="react-select"
theme={(theme) => ({
...theme,
colors: {
...theme.colors,
text: "orangered",
primary25: "var(--primary-color)",
primary50: "var(--primary-color)",
primary: "var(--secondary-color)",
},
})}
/>
</div>
</div>
);
};