deckhearth/components/AdminCatalogPagination.js

99 lines
3.8 KiB
JavaScript
Raw Permalink Normal View History

import { GlassSurface, Button, Input } from './ui';
export default function AdminCatalogPagination({
pagination,
hasMore,
loadingMore,
onLoadMore,
onLimitChange
}) {
const { page, limit, total, pages } = pagination;
if (total === 0) return null;
return (
<GlassSurface tint="mid" rim="subtle" className="mt-4 p-4">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
<div className="flex flex-wrap items-center gap-4">
<span className="text-sm" style={{ color: 'var(--text-secondary)' }}>
Showing {(page - 1) * limit + 1}–{Math.min(page * limit, total)} of {total.toLocaleString()}
</span>
<div className="flex items-center gap-2">
<label className="text-sm" style={{ color: 'var(--text-secondary)' }}>Per page:</label>
<select
value={limit}
onChange={(e) => onLimitChange(parseInt(e.target.value))}
disabled={loadingMore}
className="glass-input rounded-xl px-3 py-1.5 text-sm"
style={{
border: '1px solid var(--border)',
color: 'var(--text-primary)',
backgroundColor: 'var(--bg-tertiary)',
appearance: 'none',
backgroundImage: "url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e\")",
backgroundPosition: 'right 0.5rem center',
backgroundRepeat: 'no-repeat',
backgroundSize: '1.5em 1.5em',
paddingRight: '2rem',
minWidth: '80px'
}}
>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="200">200</option>
</select>
</div>
</div>
<div className="flex items-center gap-2">
<Button
variant="secondary"
size="sm"
onClick={() => onLoadMore()}
disabled={loadingMore || !hasMore}
leadingIcon={loadingMore && (
<span className="animate-spin inline-block h-4 w-4 border-2 border-current border-r-transparent rounded-full" />
)}
>
{hasMore ? 'Load More' : 'End of Results'}
</Button>
{pages > 1 && (
<>
<Button
variant="ghost"
size="sm"
onClick={() => onLimitChange(limit)} // placeholder - page nav handled by load more
disabled={page === 1}
leadingIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
}
>
Prev
</Button>
<span className="px-3 text-sm font-mono" style={{ color: 'var(--text-secondary)' }}>
Page {page} of {pages}
</span>
<Button
variant="ghost"
size="sm"
onClick={() => onLoadMore()}
disabled={page === pages || loadingMore}
trailingIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
}
>
Next
</Button>
</>
)}
</div>
</div>
</GlassSurface>
);
}