50 lines
2.2 KiB
TypeScript
50 lines
2.2 KiB
TypeScript
type PaginationControlsProps = {
|
||
total: number;
|
||
limit: number;
|
||
page: number;
|
||
onPageChange: (next: number) => void;
|
||
};
|
||
|
||
const numberFormatter = new Intl.NumberFormat("ru-RU");
|
||
|
||
export const PaginationControls = ({ total, limit, page, onPageChange }: PaginationControlsProps) => {
|
||
const safeLimit = Math.max(limit, 1);
|
||
const totalPages = Math.max(1, Math.ceil(Math.max(total, 0) / safeLimit));
|
||
const clampedPage = Math.min(Math.max(page, 0), totalPages - 1);
|
||
const startIndex = total === 0 ? 0 : clampedPage * safeLimit + 1;
|
||
const endIndex = total === 0 ? 0 : Math.min(total, (clampedPage + 1) * safeLimit);
|
||
const canGoPrev = clampedPage > 0;
|
||
const canGoNext = clampedPage + 1 < totalPages;
|
||
|
||
return (
|
||
<div className="flex flex-col gap-2 rounded-xl bg-slate-950/40 px-3 py-2 ring-1 ring-slate-800 sm:flex-row sm:items-center sm:justify-between">
|
||
<div className="text-xs text-slate-400">
|
||
{total === 0
|
||
? "Нет записей"
|
||
: `Показаны ${numberFormatter.format(startIndex)}–${numberFormatter.format(endIndex)} из ${numberFormatter.format(total)}`}
|
||
</div>
|
||
<div className="flex items-center gap-3">
|
||
<button
|
||
type="button"
|
||
className="rounded-lg bg-slate-900/60 px-3 py-1 text-xs font-semibold text-slate-300 ring-1 ring-slate-700 transition hover:bg-slate-800 disabled:bg-slate-900/30 disabled:text-slate-600 disabled:ring-slate-800"
|
||
onClick={() => onPageChange(Math.max(clampedPage - 1, 0))}
|
||
disabled={!canGoPrev}
|
||
>
|
||
Назад
|
||
</button>
|
||
<span className="text-xs text-slate-300">
|
||
Стр. {numberFormatter.format(clampedPage + 1)} из {numberFormatter.format(totalPages)}
|
||
</span>
|
||
<button
|
||
type="button"
|
||
className="rounded-lg bg-slate-900/60 px-3 py-1 text-xs font-semibold text-slate-300 ring-1 ring-slate-700 transition hover:bg-slate-800 disabled:bg-slate-900/30 disabled:text-slate-600 disabled:ring-slate-800"
|
||
onClick={() => onPageChange(Math.min(clampedPage + 1, totalPages - 1))}
|
||
disabled={!canGoNext}
|
||
>
|
||
Вперёд
|
||
</button>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|