kontenhumas-fe/components/table/table-pagination.tsx

144 lines
4.8 KiB
TypeScript

import { Button } from "@/components/ui/button";
import { useMediaQuery } from "@/hooks/use-media-query";
import { Table } from "@tanstack/react-table";
import {
ChevronLeft,
ChevronRight,
ChevronsLeft,
ChevronsRight,
} from "lucide-react";
import { useSearchParams, useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";
interface DataTablePaginationProps {
table: Table<any>;
totalPage: number; // Total jumlah halaman
totalData: number; // Total jumlah data
visiblePageCount?: number; // Jumlah halaman yang ditampilkan (default 5)
}
const TablePagination = ({
table,
totalPage,
totalData,
visiblePageCount = 5,
}: DataTablePaginationProps) => {
const router = useRouter();
const searchParams = useSearchParams();
const [currentPageIndex, setCurrentPageIndex] = useState<number>(1);
const isMobile = useMediaQuery("(min-width: 768px)");
if (!isMobile) {
visiblePageCount = 3;
}
useEffect(() => {
const pageFromUrl = searchParams?.get("page");
console.log("pagination: pageFromUrl :", pageFromUrl);
if (pageFromUrl) {
const pageIndex = Math.min(Math.max(1, Number(pageFromUrl)), totalPage);
setCurrentPageIndex(pageIndex);
console.log("handlePageChange: pageIndex :", pageIndex);
console.log("handlePageChange: table.setPageIndex with :", pageIndex - 1);
table.setPageIndex(pageIndex - 1); // ✅ Konversi 1-based ke 0-based
} else {
// Jika tidak ada page di URL, set ke halaman 1
setCurrentPageIndex(1);
table.setPageIndex(0); // ✅ Set ke index 0 untuk halaman 1
}
}, [searchParams, totalPage, table]);
const handlePageChange = (pageIndex: number) => {
const clampedPageIndex = Math.min(Math.max(1, pageIndex), totalPage);
const searchParams = new URLSearchParams(window.location.search);
searchParams.set("page", clampedPageIndex.toString());
console.log("handlePageChange: pageIndex :", pageIndex);
console.log("handlePageChange: clampedPageIndex :", clampedPageIndex);
console.log("handlePageChange: table.setPageIndex with :", clampedPageIndex - 1);
router.push(`${window.location.pathname}?${searchParams.toString()}`);
setCurrentPageIndex(clampedPageIndex);
table.setPageIndex(clampedPageIndex - 1); // ✅ Perbarui tabel dengan index berbasis 0
};
const generatePageNumbers = () => {
const halfVisible = Math.floor(visiblePageCount / 2);
let startPage = Math.max(1, currentPageIndex - halfVisible);
let endPage = Math.min(totalPage, startPage + visiblePageCount - 1);
if (endPage - startPage + 1 < visiblePageCount) {
startPage = Math.max(1, endPage - visiblePageCount + 1);
}
return Array.from(
{ length: endPage - startPage + 1 },
(_, i) => startPage + i
);
};
return (
<div className="flex flex-col md:flex-row items-center justify-between py-4 px-10 space-y-4 md:space-y-0">
<div className="flex-1 text-sm text-muted-foreground text-center md:text-left">
{table.getFilteredSelectedRowModel().rows.length} of {totalData} row(s)
selected.
</div>
<div className="flex items-center gap-2">
<Button
variant="outline"
size="icon"
onClick={() => handlePageChange(1)}
disabled={currentPageIndex === 1}
className="min-w-[2rem] h-8 px-2 flex items-center justify-center"
>
<ChevronsLeft className="w-4 h-4" />
</Button>
<Button
variant="outline"
size="icon"
onClick={() => handlePageChange(currentPageIndex - 1)}
disabled={currentPageIndex === 1}
className="min-w-[2rem] h-8 px-2 flex items-center justify-center"
>
<ChevronLeft className="w-4 h-4" />
</Button>
{generatePageNumbers().map((pageIndex) => (
<Button
key={pageIndex}
onClick={() => handlePageChange(pageIndex)}
size="icon"
className="min-w-[2rem] h-8 px-2 flex items-center justify-center"
variant={currentPageIndex === pageIndex ? "default" : "outline"}
>
{pageIndex}
</Button>
))}
<Button
variant="outline"
size="icon"
onClick={() => handlePageChange(currentPageIndex + 1)}
disabled={currentPageIndex === totalPage}
className="min-w-[2rem] h-8 px-2 flex items-center justify-center"
>
<ChevronRight className="w-4 h-4" />
</Button>
<Button
variant="outline"
size="icon"
onClick={() => handlePageChange(totalPage)}
disabled={currentPageIndex === totalPage}
className="min-w-[2rem] h-8 px-2 flex items-center justify-center"
>
<ChevronsRight className="w-4 h-4" />
</Button>
</div>
</div>
);
};
export default TablePagination;