Develop Frontend Components for Project, Package, and Instance Views
This commit is contained in:
98
frontend/src/components/Pagination.tsx
Normal file
98
frontend/src/components/Pagination.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import './Pagination.css';
|
||||
|
||||
interface PaginationProps {
|
||||
page: number;
|
||||
totalPages: number;
|
||||
total: number;
|
||||
limit: number;
|
||||
onPageChange: (page: number) => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function Pagination({ page, totalPages, total, limit, onPageChange, className = '' }: PaginationProps) {
|
||||
const start = (page - 1) * limit + 1;
|
||||
const end = Math.min(page * limit, total);
|
||||
|
||||
if (totalPages <= 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const getPageNumbers = (): (number | 'ellipsis')[] => {
|
||||
const pages: (number | 'ellipsis')[] = [];
|
||||
const showEllipsisStart = page > 3;
|
||||
const showEllipsisEnd = page < totalPages - 2;
|
||||
|
||||
pages.push(1);
|
||||
|
||||
if (showEllipsisStart) {
|
||||
pages.push('ellipsis');
|
||||
}
|
||||
|
||||
for (let i = Math.max(2, page - 1); i <= Math.min(totalPages - 1, page + 1); i++) {
|
||||
if (!pages.includes(i)) {
|
||||
pages.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (showEllipsisEnd) {
|
||||
pages.push('ellipsis');
|
||||
}
|
||||
|
||||
if (totalPages > 1 && !pages.includes(totalPages)) {
|
||||
pages.push(totalPages);
|
||||
}
|
||||
|
||||
return pages;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`pagination ${className}`.trim()}>
|
||||
<span className="pagination__info">
|
||||
Showing {start}-{end} of {total}
|
||||
</span>
|
||||
|
||||
<div className="pagination__controls">
|
||||
<button
|
||||
type="button"
|
||||
className="pagination__btn"
|
||||
onClick={() => onPageChange(page - 1)}
|
||||
disabled={page <= 1}
|
||||
aria-label="Previous page"
|
||||
>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||
<polyline points="15 18 9 12 15 6" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{getPageNumbers().map((pageNum, index) =>
|
||||
pageNum === 'ellipsis' ? (
|
||||
<span key={`ellipsis-${index}`} className="pagination__ellipsis">
|
||||
...
|
||||
</span>
|
||||
) : (
|
||||
<button
|
||||
key={pageNum}
|
||||
type="button"
|
||||
className={`pagination__btn pagination__page ${pageNum === page ? 'pagination__page--active' : ''}`}
|
||||
onClick={() => onPageChange(pageNum)}
|
||||
>
|
||||
{pageNum}
|
||||
</button>
|
||||
)
|
||||
)}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="pagination__btn"
|
||||
onClick={() => onPageChange(page + 1)}
|
||||
disabled={page >= totalPages}
|
||||
aria-label="Next page"
|
||||
>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||
<polyline points="9 18 15 12 9 6" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user