127 lines
4.2 KiB
TypeScript
127 lines
4.2 KiB
TypeScript
import React, { ComponentProps, Dispatch, SetStateAction } from "react";
|
|
import _ from "lodash";
|
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
import { twMerge } from "tailwind-merge";
|
|
import Row from "../layout/Row";
|
|
import Button from "../layout/Button";
|
|
import EmptyContent from "./EmptyContent";
|
|
import Span from "../layout/Span";
|
|
|
|
type Props = ComponentProps<typeof Row> & {
|
|
page?: number;
|
|
setPage?: Dispatch<SetStateAction<number>>;
|
|
count?: number;
|
|
limit?: number;
|
|
};
|
|
|
|
/**
|
|
* # Pagination Component
|
|
* @param param0
|
|
* @returns
|
|
*/
|
|
export default function Pagination({
|
|
count,
|
|
page,
|
|
setPage,
|
|
limit,
|
|
...props
|
|
}: Props) {
|
|
if (!count || !page || !limit)
|
|
return (
|
|
<EmptyContent title={`count, page, and limit are all required`} />
|
|
);
|
|
|
|
const isLimit = limit * page >= count;
|
|
|
|
const pages = Math.ceil(count / limit);
|
|
|
|
return (
|
|
<Row
|
|
{...props}
|
|
className={twMerge(
|
|
"w-full justify-between flex-nowrap",
|
|
props.className
|
|
)}
|
|
>
|
|
{pages > 1 && (
|
|
<Button
|
|
title="Next Page Button"
|
|
onClick={() => {
|
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
setPage?.((prev) => prev - 1);
|
|
}}
|
|
variant="outlined"
|
|
size="small"
|
|
className={twMerge(
|
|
"p-1",
|
|
page == 1 ? "opacity-40 pointer-events-none" : ""
|
|
)}
|
|
>
|
|
<ChevronLeft size={20} />
|
|
</Button>
|
|
)}
|
|
|
|
<Row className={twMerge("gap-6 w-full flex-nowrap justify-center")}>
|
|
<Span size="small" variant="faded">
|
|
Page {page} / {pages}
|
|
</Span>
|
|
{pages > 1 && (
|
|
<Row
|
|
className={twMerge(
|
|
"flex-nowrap overflow-x-auto p-1 max-w-[90%]"
|
|
)}
|
|
>
|
|
{Array(pages)
|
|
.fill(0)
|
|
.map((p, index) => {
|
|
const isCurrent = page == index + 1;
|
|
|
|
return (
|
|
<Button
|
|
title={`Page ${index + 1}`}
|
|
onClick={() => {
|
|
window.scrollTo({
|
|
top: 0,
|
|
behavior: "smooth",
|
|
});
|
|
setPage?.(index + 1);
|
|
}}
|
|
variant={
|
|
isCurrent ? "normal" : "outlined"
|
|
}
|
|
size="small"
|
|
color={isCurrent ? "primary" : "gray"}
|
|
className={twMerge(
|
|
"p-1 w-6 h-6 min-w-6"
|
|
)}
|
|
key={index}
|
|
>
|
|
{index + 1}
|
|
</Button>
|
|
);
|
|
})}
|
|
</Row>
|
|
)}
|
|
</Row>
|
|
|
|
{pages > 1 && (
|
|
<Button
|
|
title="Next Page Button"
|
|
onClick={() => {
|
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
setPage?.((prev) => prev + 1);
|
|
}}
|
|
variant="outlined"
|
|
size="small"
|
|
className={twMerge(
|
|
"p-1",
|
|
isLimit ? "opacity-40 pointer-events-none" : ""
|
|
)}
|
|
>
|
|
<ChevronRight size={20} />
|
|
</Button>
|
|
)}
|
|
</Row>
|
|
);
|
|
}
|