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 { Button } from '@/components/ui/button';
import type { StudentMember } from '@/lib/domain/student-member';
interface StudentTableProps {
items: StudentMember[];
page: number;
pageSize: number;
}
const COLUMN_HEADERS = [
'번호',
'회원코드',
'이름',
'아이디',
'휴대전화번호',
'이메일',
'역할',
'학교',
'학년/반/번호',
'보호자이름',
'보호자연락처',
'가입일',
'관리',
];
/**
* 학생 회원 목록 테이블 — 조회 전용(등록/수정/삭제 없음). "번호"는 저장된 값이 아니라
* 현재 페이지 기준 표시 순번(= (page-1)*pageSize + 행 인덱스 + 1)이다. 개인정보 마스킹은
* 기획 시안에서 명시적으로 해제 지시가 있어 원본 값을 그대로 노출한다.
*
* "관리" 열의 조회 버튼은 이 커밋에서는 자리만 잡고 비활성 상태다 — 클릭 시 팝업을 여는
* 상호작용과 팝업 자체는 다음 커밋(T4)에서 함께 연결한다(그때 이 셀만 클라이언트 최말단
* 컴포넌트로 교체된다). 이 테이블 자체는 Server Component로 유지한다.
*/
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>{member.phoneNumber}</TableCell>
<TableCell>{member.email}</TableCell>
<TableCell>{member.role}</TableCell>
<TableCell>{member.schoolName}</TableCell>
<TableCell>{`${member.grade}학년 ${member.classNumber}반 ${member.studentNumber}번`}</TableCell>
<TableCell>{member.guardianName}</TableCell>
<TableCell>{member.guardianPhoneNumber}</TableCell>
<TableCell>{member.joinedAt}</TableCell>
<TableCell>
<Button type="button" variant="ghost" size="sm" disabled>
조회
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
);
}