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

121 lines
4.0 KiB
TypeScript
Raw Normal View History

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');
if (pageFromUrl) {
const pageIndex = Math.min(Math.max(1, Number(pageFromUrl)), totalPage);
setCurrentPageIndex(pageIndex);
table.setPageIndex(pageIndex - 1); // Sinkronisasi tabel dengan URL
}
}, [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());
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="w-8 h-8"
>
<ChevronsLeft className="w-4 h-4" />
</Button>
<Button
variant="outline"
size="icon"
onClick={() => handlePageChange(currentPageIndex-1)}
disabled={currentPageIndex === 1}
className="w-8 h-8"
>
<ChevronLeft className="w-4 h-4" />
</Button>
{generatePageNumbers().map((pageIndex) => (
<Button
key={pageIndex}
onClick={() => handlePageChange(pageIndex)}
size="icon"
className="w-8 h-8"
variant={currentPageIndex === pageIndex ? 'default' : 'outline'}
>
{pageIndex}
</Button>
))}
<Button
variant="outline"
size="icon"
onClick={() => handlePageChange(currentPageIndex+1)}
disabled={currentPageIndex === totalPage}
className="w-8 h-8"
>
<ChevronRight className="w-4 h-4" />
</Button>
<Button
variant="outline"
size="icon"
onClick={() => handlePageChange(totalPage)}
disabled={currentPageIndex === totalPage}
className="w-8 h-8"
>
<ChevronsRight className="w-4 h-4" />
</Button>
</div>
</div>
);
};
export default TablePagination;