File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
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<Record<string, string | string[] | undefined>>;
}
/**
* 관리자 회원 목록(시안 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 (
<section className="flex flex-1 flex-col gap-6 p-8">
<h1 className="text-headline-sm text-foreground">관리자 회원 목록</h1>
<AdminMemberSearchBar query={query} />
<AdminMemberListToolbar query={query} />
<p className="text-body-md text-foreground-muted">
총 {totalCount}명 | 현재페이지 {currentPage}/{totalPages}
</p>
{items.length === 0 ? (
<Alert
title="검색 결과가 없습니다."
actions={
<Link
href={buildAdminMemberHref(query, { keyword: '', page: 1 })}
className="bg-foreground px-4 py-2 text-background"
>
확인
</Link>
}
>
다른 검색어로 다시 시도해 주세요.
</Alert>
) : (
<>
<AdminMemberTable
items={items}
page={currentPage}
pageSize={query.pageSize}
totalCount={totalCount}
currentAdminId={admin.id}
/>
<Pagination
currentPage={currentPage}
totalPages={totalPages}
buildHref={(page: number) => buildAdminMemberHref(query, { page })}
/>
</>
)}
</section>
);
}