import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow, } from '@/components/ui/table'; import { formatAdminRoleLabel, formatOptionalValue, type AdminMember, } from '@/lib/domain/admin-member'; import { AdminMemberRowActions } from './admin-member-row-actions'; interface AdminMemberTableProps { items: AdminMember[]; page: number; pageSize: number; totalCount: number; /** 현재 로그인한 관리자의 id — 본인 행의 삭제 버튼을 막는 데 쓴다. */ currentAdminId: string; } const COLUMN_HEADERS = [ '번호', '이름', '아이디', '휴대전화번호', '이메일', '역할', '생성일', '관리', ]; /** * 관리자 회원 목록 테이블(시안 ADM_ADM_101 ④). 개인정보 마스킹은 시안에 "마스킹 처리 없음"으로 * 명시돼 있어 원본 값을 그대로 노출한다. * * **"번호"는 저장된 값이 아니라 전체 건수에서 거꾸로 세는 표시 순번이다** — 시안이 6·5·4처럼 * 내림차순으로 표기하고, 목록의 기본 정렬이 생성일 최신순이라 "가장 최근에 만들어진 계정이 가장 * 큰 번호"가 된다. 이 계산은 정확한 전체 건수를 전제하는데, Repository가 전체를 받아 세기 때문에 * 그 전제가 성립한다(백엔드 `totalCount`는 신뢰할 수 없다 — Repository 주석 참조). * * 백엔드가 아직 주지 않는 항목(휴대전화번호·이메일·생성일)은 열을 그대로 유지한 채 `-`로 표시한다 * — 백엔드가 필드를 추가하면 Repository 매핑만 늘리면 이 파일은 그대로 값이 채워진다. * * "관리" 열은 행별 수정/삭제 트리거(AdminMemberRowActions)에 위임한다 — 상호작용이 필요한 것은 * 그 셀뿐이라 이 테이블 자체는 Server Component로 유지하고 최말단만 클라이언트 경계로 뗀다. */ export function AdminMemberTable({ items, page, pageSize, totalCount, currentAdminId, }: AdminMemberTableProps) { const offset = (page - 1) * pageSize; return (