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
File name
Commit message
Commit date
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeaderCell,
TableRow,
} from '@/components/ui/table';
import {
formatGradeClassNumber,
formatOptionalValue,
type StudentMember,
} from '@/lib/domain/student-member';
import { StudentRowActions } from './student-row-actions';
interface StudentTableProps {
items: StudentMember[];
page: number;
pageSize: number;
}
const COLUMN_HEADERS = [
'번호',
'회원코드',
'이름',
'아이디',
'휴대전화번호',
'이메일',
'역할',
'학교',
'학년/반/번호',
'보호자이름',
'보호자연락처',
'가입일',
'관리',
];
/**
* 학생 회원 목록 테이블 — 조회 전용(등록/수정/삭제 없음). "번호"는 저장된 값이 아니라
* 현재 페이지 기준 표시 순번(= (page-1)*pageSize + 행 인덱스 + 1)이다. 개인정보 마스킹은
* 기획 시안에서 명시적으로 해제 지시가 있어 원본 값을 그대로 노출한다.
*
* 백엔드가 아직 주지 않는 항목(휴대전화·이메일·학교·학년/반/번호·보호자·가입일)은 열을 그대로
* 유지한 채 `-`로 표시한다 — 백엔드가 필드를 추가하면 Repository 매핑만 늘리면 이 파일은
* 그대로 값이 채워진다.
*
* "관리" 열은 행별 조회 팝업 트리거(StudentRowActions)에 위임한다 — 상호작용이 필요한 것은
* 그 셀뿐이라 이 테이블 자체는 Server Component로 유지하고 최말단만 클라이언트 경계로 뗀다
* (§2.4 "'use client'는 최말단에만").
*/
export function StudentTable({ items, page, pageSize }: StudentTableProps) {
return (
<Table>
<TableHead>
<TableRow>
{COLUMN_HEADERS.map((header) => (
<TableHeaderCell key={header}>{header}</TableHeaderCell>
))}
</TableRow>
</TableHead>
<TableBody>
{items.map((member, index) => (
<TableRow key={member.id}>
<TableCell>{(page - 1) * pageSize + index + 1}</TableCell>
<TableCell>{member.memberCode}</TableCell>
<TableCell>{member.name}</TableCell>
<TableCell>{member.loginId}</TableCell>
<TableCell>{formatOptionalValue(member.phoneNumber)}</TableCell>
<TableCell>{formatOptionalValue(member.email)}</TableCell>
<TableCell>{member.role}</TableCell>
<TableCell>{formatOptionalValue(member.schoolName)}</TableCell>
<TableCell>{formatGradeClassNumber(member)}</TableCell>
<TableCell>{formatOptionalValue(member.guardianName)}</TableCell>
<TableCell>
{formatOptionalValue(member.guardianPhoneNumber)}
</TableCell>
<TableCell>{formatOptionalValue(member.joinedAt)}</TableCell>
<TableCell>
<StudentRowActions member={member} />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
);
}