import { Key, History, Edit } from "lucide-react"; import { useState } from "react"; import { User } from "@/types/user"; import { Button } from "@/components/ui/button"; import { Switch } from "@/components/ui/switch"; import { PaginationInfo } from "@/components/common/Pagination"; import { ResponsiveDataView, RDVColumn, RDVCardField } from "@/components/common/ResponsiveDataView"; import { UserStatusConfirmDialog } from "./UserStatusConfirmDialog"; import { UserHistoryModal } from "./UserHistoryModal"; import { useAuth } from "@/hooks/useAuth"; interface UserTableProps { users: User[]; isLoading: boolean; paginationInfo: PaginationInfo; onStatusToggle: (user: User, newStatus: string) => void; onPasswordReset: (userId: string, userName: string) => void; onEdit: (user: User) => void; t?: (key: string, params?: Record) => string; } /** * 사용자 목록 테이블 컴포넌트 */ export function UserTable({ users, isLoading, paginationInfo, onStatusToggle, onPasswordReset, onEdit, t: tProp, }: UserTableProps) { // 다국어 함수 (prop이 없으면 한국어 기본값 사용) const _t = tProp || ((key: string) => { const defaults: Record = { "table.sabun": "사번", "table.company": "회사", "table.dept": "부서명", "table.position": "직책", "table.userId": "사용자 ID", "table.userName": "사용자명", "table.phone": "전화번호", "table.email": "이메일", "table.regDate": "등록일", "table.status": "상태", "table.dept.short": "부서", "table.contact": "연락처", "table.empty": "등록된 사용자가 없습니다.", "table.actions": "작업", "action.edit.user": "사용자 정보 수정", "action.reset.password": "비밀번호 초기화", "action.view.history": "변경이력 조회", }; return defaults[key] || key; }); const { user: currentUser } = useAuth(); const isSuperAdmin = currentUser?.companyCode === "*" && currentUser?.userType === "SUPER_ADMIN"; // 확인 모달 상태 관리 const [confirmDialog, setConfirmDialog] = useState<{ isOpen: boolean; user: User | null; newStatus: string; }>({ isOpen: false, user: null, newStatus: "", }); // 히스토리 모달 상태 관리 const [historyModal, setHistoryModal] = useState<{ isOpen: boolean; userId: string; userName: string; }>({ isOpen: false, userId: "", userName: "", }); // NO 컬럼 계산 함수 (페이지네이션 고려) const getRowNumber = (index: number) => { return paginationInfo.startItem + index; }; // 날짜 포맷팅 함수 const formatDate = (dateString: string) => { if (!dateString) return "-"; return dateString.split(" ")[0]; }; // 상태 토글 핸들러 (확인 모달 표시) const handleStatusToggle = (user: User, checked: boolean) => { const newStatus = checked ? "active" : "inactive"; setConfirmDialog({ isOpen: true, user, newStatus, }); }; // 상태 변경 확인 const handleConfirmStatusChange = () => { if (confirmDialog.user) { onStatusToggle(confirmDialog.user, confirmDialog.newStatus); } setConfirmDialog({ isOpen: false, user: null, newStatus: "" }); }; // 상태 변경 취소 const handleCancelStatusChange = () => { setConfirmDialog({ isOpen: false, user: null, newStatus: "" }); }; // 변경이력 모달 열기 const handleOpenHistoryModal = (user: User) => { setHistoryModal({ isOpen: true, userId: user.userId, userName: user.userName || user.userId, }); }; // 변경이력 모달 닫기 const handleCloseHistoryModal = () => { setHistoryModal({ isOpen: false, userId: "", userName: "", }); }; // 데스크톱 테이블 컬럼 정의 const columns: RDVColumn[] = [ { key: "no", label: "No", width: "60px", render: (_value, _row, index) => ( {getRowNumber(index)} ), }, { key: "sabun", label: _t("table.sabun"), width: "80px", hideOnMobile: true, render: (value) => {value || "-"}, }, ...(isSuperAdmin ? [ { key: "companyCode" as keyof User, label: _t("table.company"), width: "120px", hideOnMobile: true, render: (value: any, user: User) => ( {(user as any).companyName || value || "-"} ), }, ] : []), { key: "deptName", label: _t("table.dept"), width: "120px", hideOnMobile: true, render: (value) => {value || "-"}, }, { key: "positionName", label: _t("table.position"), width: "100px", hideOnMobile: true, render: (value) => {value || "-"}, }, { key: "userId", label: _t("table.userId"), width: "120px", hideOnMobile: true, render: (value) => {value}, }, { key: "userName", label: _t("table.userName"), width: "100px", hideOnMobile: true, render: (value) => {value}, }, { key: "tel", label: _t("table.phone"), width: "120px", hideOnMobile: true, render: (_value, row) => {row.tel || row.cellPhone || "-"}, }, { key: "email", label: _t("table.email"), width: "200px", hideOnMobile: true, className: "max-w-[200px] truncate", render: (value, row) => ( {value || "-"} ), }, { key: "regDate", label: _t("table.regDate"), width: "100px", hideOnMobile: true, render: (value) => {formatDate(value || "")}, }, { key: "status", label: _t("table.status"), width: "120px", hideOnMobile: true, render: (_value, row) => (
handleStatusToggle(row, checked)} aria-label={`${row.userName} 상태 토글`} />
), }, ]; // 모바일 카드 필드 정의 const cardFields: RDVCardField[] = [ { label: _t("table.sabun"), render: (user) => {user.sabun || "-"}, hideEmpty: true, }, ...(isSuperAdmin ? [ { label: _t("table.company"), render: (user: User) => ( {(user as any).companyName || user.companyCode || ""} ), hideEmpty: true, }, ] : []), { label: _t("table.dept.short"), render: (user) => {user.deptName || ""}, hideEmpty: true, }, { label: _t("table.position"), render: (user) => {user.positionName || ""}, hideEmpty: true, }, { label: _t("table.contact"), render: (user) => {user.tel || user.cellPhone || ""}, hideEmpty: true, }, { label: _t("table.email"), render: (user) => {user.email || ""}, hideEmpty: true, }, { label: _t("table.regDate"), render: (user) => {formatDate(user.regDate || "")}, }, ]; return ( <> data={users} columns={columns} keyExtractor={(u) => u.userId} isLoading={isLoading} emptyMessage={_t("table.empty")} skeletonCount={10} cardTitle={(u) => u.userName || ""} cardSubtitle={(u) => {u.userId}} cardHeaderRight={(u) => ( handleStatusToggle(u, checked)} aria-label={`${u.userName} 상태 토글`} /> )} cardFields={cardFields} actionsLabel={_t("table.actions")} actionsWidth="200px" renderActions={(user) => ( <> )} /> {/* 상태 변경 확인 모달 */} {/* 사용자 변경이력 모달 */} ); }