"use client"; import * as React from "react"; import { type ColumnDef } from "@tanstack/react-table"; import { Checkbox } from "@/components/ui/checkbox"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Pencil, Check, X } from "lucide-react"; import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"; import { EvaluationTargetWithDepartments } from "@/db/schema"; import type { DataTableRowAction } from "@/types/table"; import { formatDate } from "@/lib/utils"; interface GetColumnsProps { setRowAction: React.Dispatch | null>>; } // ✅ 모든 헬퍼 함수들을 컴포넌트 외부로 이동 (매번 재생성 방지) const getStatusBadgeVariant = (status: string) => { switch (status) { case "PENDING": return "secondary"; case "CONFIRMED": return "default"; case "EXCLUDED": return "destructive"; default: return "outline"; } }; const getStatusText = (status: string) => { const statusMap = { PENDING: "검토 중", CONFIRMED: "확정", EXCLUDED: "제외" }; return statusMap[status] || status; }; const getConsensusBadge = (consensusStatus: boolean | null) => { if (consensusStatus === null) { return 검토 중; } if (consensusStatus === true) { return 의견 일치; } return 의견 불일치; }; const getDivisionBadge = (division: string) => { return ( {division === "OCEAN" ? "해양" : "조선"} ); }; const getMaterialTypeBadge = (materialType: string) => { const typeMap = { EQUIPMENT: "기자재", BULK: "벌크", EQUIPMENT_BULK: "기자재/벌크" }; return {typeMap[materialType] || materialType}; }; const getDomesticForeignBadge = (domesticForeign: string) => { return ( {domesticForeign === "DOMESTIC" ? "내자" : "외자"} ); }; // ✅ 평가 대상 여부 표시 함수 const getEvaluationTargetBadge = (isTarget: boolean | null) => { if (isTarget === null) { return 미정; } return isTarget ? ( 평가 대상 ) : ( 평가 제외 ); }; export function getEvaluationTargetsColumns({ setRowAction }: GetColumnsProps): ColumnDef[] { return [ // ✅ Checkbox { id: "select", header: ({ table }) => ( table.toggleAllPageRowsSelected(!!v)} aria-label="select all" className="translate-y-0.5" /> ), cell: ({ row }) => ( row.toggleSelected(!!v)} aria-label="select row" className="translate-y-0.5" /> ), size: 40, enableSorting: false, enableHiding: false, }, // ✅ 기본 정보 { accessorKey: "evaluationYear", header: ({ column }) => , cell: ({ row }) => {row.getValue("evaluationYear")}, size: 100, }, { accessorKey: "division", header: ({ column }) => , cell: ({ row }) => getDivisionBadge(row.getValue("division")), size: 80, }, { accessorKey: "status", header: ({ column }) => , cell: ({ row }) => { const status = row.getValue("status"); return ( {getStatusText(status)} ); }, size: 100, }, { accessorKey: "consensusStatus", header: ({ column }) => , cell: ({ row }) => getConsensusBadge(row.getValue("consensusStatus")), size: 100, }, // ✅ 벤더 정보 그룹 { id: "vendorInfo", header: "벤더 정보", columns: [ { accessorKey: "vendorCode", header: ({ column }) => , cell: ({ row }) => ( {row.getValue("vendorCode")} ), size: 120, }, { accessorKey: "vendorName", header: ({ column }) => , cell: ({ row }) => (
("vendorName")!}> {row.getValue("vendorName") as string}
), size: 200, }, { accessorKey: "domesticForeign", header: ({ column }) => , cell: ({ row }) => getDomesticForeignBadge(row.getValue("domesticForeign")), size: 80, }, { accessorKey: "materialType", header: ({ column }) => , cell: ({ row }) => getMaterialTypeBadge(row.getValue("materialType")), size: 120, }, ] }, // ✅ 발주 담당자 { id: "orderReviewer", header: "발주 담당자", columns: [ { accessorKey: "orderReviewerName", header: ({ column }) => , cell: ({ row }) => { const reviewerName = row.getValue("orderReviewerName"); return reviewerName ? (
{reviewerName}
) : ( - ); }, size: 120, }, { accessorKey: "orderIsApproved", header: ({ column }) => , cell: ({ row }) => { const isApproved = row.getValue("orderIsApproved"); return getEvaluationTargetBadge(isApproved); }, size: 120, }, ] }, // ✅ 조달 담당자 { id: "procurementReviewer", header: "조달 담당자", columns: [ { accessorKey: "procurementReviewerName", header: ({ column }) => , cell: ({ row }) => { const reviewerName = row.getValue("procurementReviewerName"); return reviewerName ? (
{reviewerName}
) : ( - ); }, size: 120, }, { accessorKey: "procurementIsApproved", header: ({ column }) => , cell: ({ row }) => { const isApproved = row.getValue("procurementIsApproved"); return getEvaluationTargetBadge(isApproved); }, size: 120, }, ] }, // ✅ 품질 담당자 { id: "qualityReviewer", header: "품질 담당자", columns: [ { accessorKey: "qualityReviewerName", header: ({ column }) => , cell: ({ row }) => { const reviewerName = row.getValue("qualityReviewerName"); return reviewerName ? (
{reviewerName}
) : ( - ); }, size: 120, }, { accessorKey: "qualityIsApproved", header: ({ column }) => , cell: ({ row }) => { const isApproved = row.getValue("qualityIsApproved"); return getEvaluationTargetBadge(isApproved); }, size: 120, }, ] }, // ✅ 설계 담당자 { id: "designReviewer", header: "설계 담당자", columns: [ { accessorKey: "designReviewerName", header: ({ column }) => , cell: ({ row }) => { const reviewerName = row.getValue("designReviewerName"); return reviewerName ? (
{reviewerName}
) : ( - ); }, size: 120, }, { accessorKey: "designIsApproved", header: ({ column }) => , cell: ({ row }) => { const isApproved = row.getValue("designIsApproved"); return getEvaluationTargetBadge(isApproved); }, size: 120, }, ] }, // ✅ CS 담당자 { id: "csReviewer", header: "CS 담당자", columns: [ { accessorKey: "csReviewerName", header: ({ column }) => , cell: ({ row }) => { const reviewerName = row.getValue("csReviewerName"); return reviewerName ? (
{reviewerName}
) : ( - ); }, size: 120, }, { accessorKey: "csIsApproved", header: ({ column }) => , cell: ({ row }) => { const isApproved = row.getValue("csIsApproved"); return getEvaluationTargetBadge(isApproved); }, size: 120, }, ] }, // ✅ 의견 및 결과 { accessorKey: "adminComment", header: ({ column }) => , cell: ({ row }) => { const comment = row.getValue("adminComment"); return comment ? (
{comment}
) : ( - ); }, size: 150, }, { accessorKey: "consolidatedComment", header: ({ column }) => , cell: ({ row }) => { const comment = row.getValue("consolidatedComment"); return comment ? (
{comment}
) : ( - ); }, size: 150, }, { accessorKey: "confirmedAt", header: ({ column }) => , cell: ({ row }) => { const confirmedAt = row.getValue("confirmedAt"); return { confirmedAt ? formatDate(confirmedAt, "KR") :'-'}; }, size: 100, }, { accessorKey: "createdAt", header: ({ column }) => , cell: ({ row }) => { const createdAt = row.getValue("createdAt"); return {formatDate(createdAt, "KR")}; }, size: 100, }, // ✅ Actions - 가장 안전하게 처리 { id: "actions", enableHiding: false, size: 40, minSize: 40, cell: ({ row }) => { // ✅ 함수를 직접 정의해서 매번 새로 생성되지 않도록 처리 const handleEdit = () => { setRowAction({ row, type: "update" }); }; return (
); }, }, ]; }