/** * Component: LogsPagination * Documentation: documentation/admin-dashboard.md * * Prev/next + jump-to-page + page-size selector + "Page X of Y · N total logs". * Keyboard accessible. Each interactive element ≥ 44×44 touch target. * Reading the page-size opens registers a pause-on-interact reason. */ 'use client'; import { useEffect, useState } from 'react'; import { VALID_LIMITS, ValidLimit, LogsPagination as PaginationData } from '../types'; import { useAutoRefreshControl } from '../hooks/useAutoRefreshControl'; interface LogsPaginationProps { pagination: PaginationData; onPageChange: (next: number) => void; onLimitChange: (next: ValidLimit) => void; } export function LogsPagination({ pagination, onPageChange, onLimitChange, }: LogsPaginationProps) { const { page, limit, total, totalPages } = pagination; const [jumpValue, setJumpValue] = useState(String(page)); const [limitFocused, setLimitFocused] = useState(false); const { register, unregister } = useAutoRefreshControl(); // Keep jump input in sync when page changes from outside. useEffect(() => { setJumpValue(String(page)); }, [page]); // Pause auto-refresh while the limit dropdown is focused/open. useEffect(() => { if (limitFocused) register('page-size-dropdown'); else unregister('page-size-dropdown'); return () => unregister('page-size-dropdown'); }, [limitFocused, register, unregister]); const submitJump = () => { const parsed = Number.parseInt(jumpValue, 10); if (!Number.isFinite(parsed)) { setJumpValue(String(page)); return; } const clamped = Math.min(Math.max(1, parsed), Math.max(1, totalPages)); if (clamped !== page) onPageChange(clamped); setJumpValue(String(clamped)); }; return (
{/* Summary + limit */}
Page {page} of{' '} {Math.max(1, totalPages)} {' · '} {total.toLocaleString()} {' '} {total === 1 ? 'log' : 'logs'}
{/* Nav controls */}
); }