feat(admin): 활동 로그 페이지에 페이지 번호 직접 입력 기능 추가

- 페이지네이션을 3-column grid로 배치해 버튼 그룹은 중앙 정렬, 오른쪽 구석에 입력 박스 추가
- 숫자만 입력, Enter 또는 blur 시 페이지 이동 (1~totalPages로 clamp)
- Enter 시 blur() 호출로 포커스 자동 해제

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
caadiq 2026-04-22 11:47:59 +09:00
parent 8ece4b1850
commit 39bb6f77f9

View file

@ -27,6 +27,7 @@ function Logs() {
const [dateFrom, setDateFrom] = useState(''); const [dateFrom, setDateFrom] = useState('');
const [dateTo, setDateTo] = useState(''); const [dateTo, setDateTo] = useState('');
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [pageInput, setPageInput] = useState('1');
const [actorDropdownOpen, setActorDropdownOpen] = useState(false); const [actorDropdownOpen, setActorDropdownOpen] = useState(false);
const [categoryDropdownOpen, setCategoryDropdownOpen] = useState(false); const [categoryDropdownOpen, setCategoryDropdownOpen] = useState(false);
const [selectedLog, setSelectedLog] = useState(null); const [selectedLog, setSelectedLog] = useState(null);
@ -65,6 +66,20 @@ function Logs() {
const total = data?.total || 0; const total = data?.total || 0;
const totalPages = data?.totalPages || 0; const totalPages = data?.totalPages || 0;
//
useEffect(() => { setPageInput(String(currentPage)); }, [currentPage]);
const goToPageFromInput = () => {
const n = parseInt(pageInput, 10);
if (!Number.isFinite(n) || n < 1) {
setPageInput(String(currentPage));
return;
}
const clamped = Math.min(totalPages, n);
setCurrentPage(clamped);
setPageInput(String(clamped));
};
// //
const toggleCategory = (cat) => { const toggleCategory = (cat) => {
setSelectedCategories((prev) => setSelectedCategories((prev) =>
@ -343,7 +358,9 @@ function Logs() {
{/* 페이지네이션 */} {/* 페이지네이션 */}
{totalPages > 1 && ( {totalPages > 1 && (
<div className="flex items-center justify-center gap-2 mt-6"> <div className="grid grid-cols-3 items-center mt-6">
<div />
<div className="flex items-center justify-center gap-2">
<button <button
onClick={() => setCurrentPage((p) => Math.max(1, p - 1))} onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}
disabled={currentPage === 1} disabled={currentPage === 1}
@ -390,6 +407,26 @@ function Logs() {
<ChevronRight size={18} /> <ChevronRight size={18} />
</button> </button>
</div> </div>
<div className="flex items-center justify-end gap-1.5">
<input
type="text"
inputMode="numeric"
value={pageInput}
onChange={(e) => setPageInput(e.target.value.replace(/\D/g, ''))}
onBlur={goToPageFromInput}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
goToPageFromInput();
e.currentTarget.blur();
}
}}
className="w-12 h-9 text-center tabular-nums border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"
aria-label="페이지 번호 입력"
/>
<span className="text-sm text-gray-400 tabular-nums">/ {totalPages}</span>
</div>
</div>
)} )}
</div> </div>