Aktueller Stand
This commit is contained in:
91
components/Pagination.tsx
Normal file
91
components/Pagination.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
"use client";
|
||||
|
||||
type PaginationProps = {
|
||||
page: number;
|
||||
totalPages: number;
|
||||
onPageChange: (page: number) => void;
|
||||
pageSize: number;
|
||||
onPageSizeChange: (pageSize: number) => void;
|
||||
pageSizeOptions?: number[];
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export default function Pagination({
|
||||
page,
|
||||
totalPages,
|
||||
onPageChange,
|
||||
pageSize,
|
||||
onPageSizeChange,
|
||||
pageSizeOptions = [20, 50, 100],
|
||||
className
|
||||
}: PaginationProps) {
|
||||
const windowPages = Array.from({ length: totalPages }, (_, i) => i + 1).filter(
|
||||
(pageNumber) =>
|
||||
pageNumber === 1 ||
|
||||
pageNumber === totalPages ||
|
||||
Math.abs(pageNumber - page) <= 2
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`flex flex-wrap items-center justify-between gap-2 text-sm text-slate-600 ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
<span>Seite {page} von {totalPages}</span>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<select
|
||||
value={pageSize}
|
||||
onChange={(event) => onPageSizeChange(Number(event.target.value))}
|
||||
className="rounded-full border border-slate-200 bg-white px-2 py-1 text-xs text-slate-700"
|
||||
aria-label="Einträge pro Seite"
|
||||
>
|
||||
{pageSizeOptions.map((option) => (
|
||||
<option key={option} value={option}>
|
||||
{option} pro Seite
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-full border border-slate-200 px-3 py-1 text-xs text-slate-700"
|
||||
onClick={() => onPageChange(Math.max(1, page - 1))}
|
||||
disabled={page <= 1}
|
||||
>
|
||||
Zurück
|
||||
</button>
|
||||
<div className="flex flex-wrap items-center gap-1">
|
||||
{windowPages.map((pageNumber, index) => {
|
||||
const previous = windowPages[index - 1];
|
||||
const gap = previous && pageNumber - previous > 1;
|
||||
return (
|
||||
<span key={pageNumber} className="flex items-center gap-1">
|
||||
{gap && <span className="px-1 text-xs text-slate-400">…</span>}
|
||||
<button
|
||||
type="button"
|
||||
className={`rounded-full border px-2 py-1 text-xs ${
|
||||
pageNumber === page
|
||||
? "border-slate-900 bg-slate-900 text-white"
|
||||
: "border-slate-200 text-slate-700"
|
||||
}`}
|
||||
onClick={() => onPageChange(pageNumber)}
|
||||
aria-current={pageNumber === page ? "page" : undefined}
|
||||
>
|
||||
{pageNumber}
|
||||
</button>
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-full border border-slate-200 px-3 py-1 text-xs text-slate-700"
|
||||
onClick={() => onPageChange(Math.min(totalPages, page + 1))}
|
||||
disabled={page >= totalPages}
|
||||
>
|
||||
Weiter
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user