import type { Metadata } from 'next'; import Link from 'next/link'; import { Alert } from '@/components/ui/alert'; import { Pagination } from '@/components/ui/pagination'; import { verifySession } from '@/lib/auth/dal'; import { fetchAdminMembers } from '@/lib/data/repositories/admin-member-repository'; import { buildAdminMemberHref, parseAdminMemberQuery, } from '@/lib/domain/admin-member-query'; import { AdminMemberListToolbar } from './_components/admin-member-list-toolbar'; import { AdminMemberSearchBar } from './_components/admin-member-search-bar'; import { AdminMemberTable } from './_components/admin-member-table'; export const metadata: Metadata = { title: '관리자 회원', }; interface PageProps { searchParams: Promise>; } /** * 관리자 회원 목록(시안 ADM_ADM_101). * * 학생 회원 목록과 달리 전체 건수가 **확정값**이라 페이지 수를 그대로 계산한다 — Repository가 * 백엔드 페이징을 쓰지 않고 전체를 받아 직접 세기 때문이다(그 이유는 Repository 주석 참조). * * `verifySession()`의 반환값을 목록까지 내려보내는 이유는 본인 계정의 삭제 버튼을 막기 위해서다 * (시안 ⑤). 실제 차단은 Server Action이 다시 확인한다. */ export default async function Page({ searchParams }: PageProps) { const admin = await verifySession(); const query = parseAdminMemberQuery(await searchParams); const { items, totalCount } = await fetchAdminMembers(query); const totalPages = Math.max(1, Math.ceil(totalCount / query.pageSize)); // 요청 페이지가 범위를 벗어나면(예: 삭제로 마지막 페이지가 사라짐) 마지막 페이지로 맞춘다 — // 표의 순번 계산도 이 값을 기준으로 해야 헤더의 "현재페이지"와 어긋나지 않는다. const currentPage = Math.min(query.page, totalPages); return (

관리자 회원 목록

총 {totalCount}명 | 현재페이지 {currentPage}/{totalPages}

{items.length === 0 ? ( 확인 } > 다른 검색어로 다시 시도해 주세요. ) : ( <> buildAdminMemberHref(query, { page })} /> )}
); }