Files
panel/resources/scripts/components/elements/Pagination.tsx
2022-12-11 04:04:12 +00:00

66 lines
2.0 KiB
TypeScript

import { PaginatedResult } from '@/api/http';
import { ReactNode, useEffect } from 'react';
import { Pagination as MantinePagination } from '@mantine/core'
interface RenderFuncProps<T> {
items: T[];
isLastPage: boolean;
isFirstPage: boolean;
}
interface Props<T> {
data: PaginatedResult<T>;
showGoToLast?: boolean;
showGoToFirst?: boolean;
onPageSelect: (page: number) => void;
children: (props: RenderFuncProps<T>) => ReactNode;
}
const Pagination = <T,>({ data: { items, pagination }, onPageSelect, children }: Props<T>) => {
const isFirstPage = pagination.currentPage === 1;
const isLastPage = pagination.currentPage >= pagination.totalPages;
const pages = [];
// Start two spaces before the current page. If that puts us before the starting page default
// to the first page as the starting point.
const start = Math.max(pagination.currentPage - 2, 1);
const end = Math.min(pagination.totalPages, pagination.currentPage + 5);
for (let i = start; i <= end; i++) {
pages.push(i);
}
useEffect(() => {
if (pagination.currentPage > pagination.totalPages) {
onPageSelect(pagination.totalPages);
}
}, [])
useEffect(() => {
const url = new URL(window.location.href);
// don't add page param if it's the first page
if (pagination.currentPage === 1) {
url.searchParams.delete('page');
window.history.pushState({}, '', url.toString());
return;
}
url.searchParams.set('page', pagination.currentPage.toString());
window.history.pushState({}, '', url.toString());
}, [pagination])
return (
<>
{children({ items, isFirstPage, isLastPage })}
{pages.length > 1 && (
<div className='flex justify-end mt-3'>
<MantinePagination onChange={onPageSelect} page={pagination.currentPage} total={pagination.totalPages}/>
</div>
)}
</>
);
}
export default Pagination