diff options
Diffstat (limited to 'lib/evaluation/table/evaluation-columns.tsx')
| -rw-r--r-- | lib/evaluation/table/evaluation-columns.tsx | 455 |
1 files changed, 338 insertions, 117 deletions
diff --git a/lib/evaluation/table/evaluation-columns.tsx b/lib/evaluation/table/evaluation-columns.tsx index dca19ddb..e8b51b57 100644 --- a/lib/evaluation/table/evaluation-columns.tsx +++ b/lib/evaluation/table/evaluation-columns.tsx @@ -1,6 +1,4 @@ -// ================================================================ -// 1. PERIODIC EVALUATIONS COLUMNS -// ================================================================ +// components/evaluation/evaluation-columns.tsx - 집계 모드 지원 업데이트 "use client"; import * as React from "react"; @@ -8,33 +6,69 @@ 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, Eye, MessageSquare, Check, X, Clock, FileText, Circle, Ellipsis } from "lucide-react"; +import { Pencil, Eye, MessageSquare, Check, X, Clock, FileText, Circle, Ellipsis, BarChart3 } from "lucide-react"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"; -import { PeriodicEvaluationView } from "@/db/schema"; +import { PeriodicEvaluationView, PeriodicEvaluationAggregatedView } from "@/db/schema"; import { DataTableRowAction } from "@/types/table"; import { vendortypeMap } from "@/types/evaluation"; - - interface GetColumnsProps { - setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<PeriodicEvaluationView> | null>>; + setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<PeriodicEvaluationView | PeriodicEvaluationAggregatedView> | null>>; + viewMode?: "detailed" | "aggregated"; } -// 상태별 색상 매핑 +// 집계 모드용 division 배지 +const getDivisionBadgeWithAggregation = ( + division: string, + evaluationCount?: number, + divisions?: string +) => { + if (division === "BOTH") { + return ( + <div className="flex items-center gap-1"> + <Badge variant="outline" className="bg-purple-50 text-purple-700 border-purple-200"> + 통합 + </Badge> + {evaluationCount && evaluationCount > 1 && ( + <TooltipProvider> + <Tooltip> + <TooltipTrigger> + <Badge variant="secondary" className="text-xs"> + {evaluationCount}개 + </Badge> + </TooltipTrigger> + <TooltipContent> + <p>{divisions?.replace(',', ', ')} 평가 통합</p> + </TooltipContent> + </Tooltip> + </TooltipProvider> + )} + </div> + ); + } + + return ( + <Badge variant={division === "PLANT" ? "default" : "secondary"}> + {division === "PLANT" ? "해양" : "조선"} + </Badge> + ); +}; + +// 기존 함수들은 그대로 유지... const getStatusBadgeVariant = (status: string) => { switch (status) { - case "PENDING_SUBMISSION": - return "outline"; - case "SUBMITTED": - return "secondary"; - case "IN_REVIEW": - return "default"; - case "REVIEW_COMPLETED": - return "default"; - case "FINALIZED": - return "default"; - default: - return "outline"; + case "PENDING_SUBMISSION": return "outline"; + case "SUBMITTED": return "secondary"; + case "IN_REVIEW": return "default"; + case "REVIEW_COMPLETED": return "default"; + case "FINALIZED": return "default"; + default: return "outline"; } }; @@ -54,7 +88,6 @@ const getStatusLabel = (status: string) => { const getDepartmentStatusBadge = (status: string | null) => { if (!status) return ( <div className="flex items-center gap-1"> - {/* <Circle className="w-4 h-4 fill-gray-300 text-gray-300" /> */} <span className="text-xs text-gray-500">-</span> </div> ); @@ -63,7 +96,6 @@ const getDepartmentStatusBadge = (status: string | null) => { case "NOT_ASSIGNED": return ( <div className="flex items-center gap-1"> - {/* <Circle className="w-4 h-4 fill-gray-400 text-gray-400" /> */} <span className="text-xs text-gray-600">미지정</span> </div> ); @@ -71,73 +103,44 @@ const getDepartmentStatusBadge = (status: string | null) => { return ( <div className="flex items-center gap-1"> <div className="w-4 h-4 rounded-full bg-red-500 shadow-sm" /> - - {/* <span className="text-xs text-red-600">시작전</span> */} </div> ); case "IN_PROGRESS": return ( <div className="flex items-center gap-1"> <div className="w-4 h-4 rounded-full bg-yellow-500 shadow-sm" /> - {/* <span className="text-xs text-yellow-600">진행중</span> */} </div> ); case "COMPLETED": return ( <div className="flex items-center gap-1"> <div className="w-4 h-4 rounded-full bg-green-500 shadow-sm" /> - {/* <span className="text-xs text-green-600">완료</span> */} </div> ); default: return ( <div className="flex items-center gap-1"> - {/* <Circle className="w-4 h-4 fill-gray-300 text-gray-300" /> */} <span className="text-xs text-gray-500">-</span> </div> ); } }; -// 부서명 라벨 -const DEPARTMENT_LABELS = { - ORDER_EVAL: "발주", - PROCUREMENT_EVAL: "조달", - QUALITY_EVAL: "품질", - DESIGN_EVAL: "설계", - CS_EVAL: "CS" -} as const; // 등급별 색상 const getGradeBadgeVariant = (grade: string | null) => { if (!grade) return "outline"; switch (grade) { - case "S": - return "default"; - case "A": - return "secondary"; - case "B": - return "outline"; - case "C": - return "destructive"; - case "D": - return "destructive"; - default: - return "outline"; + case "S": return "default"; + case "A": return "secondary"; + case "B": return "outline"; + case "C": return "destructive"; + case "D": return "destructive"; + default: return "outline"; } }; -// 구분 배지 -const getDivisionBadge = (division: string) => { - return ( - <Badge variant={division === "PLANT" ? "default" : "secondary"}> - {division === "PLANT" ? "해양" : "조선"} - </Badge> - ); -}; - // 자재구분 배지 const getMaterialTypeBadge = (materialType: string) => { - return <Badge variant="outline">{vendortypeMap[materialType] || materialType}</Badge>; }; @@ -150,18 +153,12 @@ const getDomesticForeignBadge = (domesticForeign: string) => { ); }; -// 진행률 배지 -const getProgressBadge = (completed: number, total: number) => { - if (total === 0) return <Badge variant="outline">-</Badge>; +export function getPeriodicEvaluationsColumns({ + setRowAction, + viewMode = "detailed" +}: GetColumnsProps): ColumnDef<PeriodicEvaluationView | PeriodicEvaluationAggregatedView>[] { - const percentage = Math.round((completed / total) * 100); - const variant = percentage === 100 ? "default" : percentage >= 50 ? "secondary" : "destructive"; - - return <Badge variant={variant}>{completed}/{total} ({percentage}%)</Badge>; -}; - -export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): ColumnDef<PeriodicEvaluationView>[] { - return [ + const baseColumns: ColumnDef<PeriodicEvaluationView | PeriodicEvaluationAggregatedView>[] = [ // ═══════════════════════════════════════════════════════════════ // 선택 및 기본 정보 // ═══════════════════════════════════════════════════════════════ @@ -196,24 +193,37 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="평가년도" />, cell: ({ row }) => <span className="font-medium">{row.original.evaluationYear}</span>, size: 100, + meta: { + excelHeader: "평가년도", + }, }, - // ░░░ 평가기간 ░░░ - // { - // accessorKey: "evaluationPeriod", - // header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="평가기간" />, - // cell: ({ row }) => ( - // <Badge variant="outline">{row.getValue("evaluationPeriod")}</Badge> - // ), - // size: 100, - // }, - - // ░░░ 구분 ░░░ + // ░░░ 구분 ░░░ - 집계 모드에 따라 다르게 렌더링 { accessorKey: "division", header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="구분" />, - cell: ({ row }) => getDivisionBadge(row.original.division || ""), - size: 80, + cell: ({ row }) => { + const division =viewMode === "aggregated"?"BOTH": row.original.division || ""; + + if (viewMode === "aggregated") { + const aggregatedRow = row.original as PeriodicEvaluationAggregatedView; + return getDivisionBadgeWithAggregation( + division, + aggregatedRow.evaluationCount, + aggregatedRow.divisions + ); + } + + return ( + <Badge variant={division === "PLANT" ? "default" : "secondary"}> + {division === "PLANT" ? "해양" : "조선"} + </Badge> + ); + }, + size: viewMode === "aggregated" ? 120 : 80, + meta: { + excelHeader: "구분", + }, }, { @@ -221,9 +231,11 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="Status" />, cell: ({ row }) => getStatusLabel(row.original.status || ""), size: 80, + meta: { + excelHeader: "Status", + }, }, - // ═══════════════════════════════════════════════════════════════ // 협력업체 정보 // ═══════════════════════════════════════════════════════════════ @@ -237,6 +249,9 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): <span className="font-mono text-sm">{row.original.vendorCode}</span> ), size: 120, + meta: { + excelHeader: "벤더 코드", + }, }, { @@ -248,6 +263,9 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): </div> ), size: 200, + meta: { + excelHeader: "벤더명", + }, }, { @@ -255,6 +273,9 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="내외자" />, cell: ({ row }) => getDomesticForeignBadge(row.original.domesticForeign || ""), size: 80, + meta: { + excelHeader: "내외자", + }, }, { @@ -262,22 +283,87 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="자재구분" />, cell: ({ row }) => getMaterialTypeBadge(row.original.materialType || ""), size: 120, + meta: { + excelHeader: "자재구분", + }, }, ] }, + + // 집계 모드에서만 보이는 평가 개수 컬럼 + ...(viewMode === "aggregated" ? [{ + accessorKey: "evaluationCount", + header: ({ column }) => ( + <div className="flex items-center gap-1"> + <BarChart3 className="h-4 w-4" /> + <DataTableColumnHeaderSimple column={column} title="평가수" /> + </div> + ), + cell: ({ row }) => { + const aggregatedRow = row.original as PeriodicEvaluationAggregatedView; + const count = aggregatedRow.evaluationCount || 1; + + return ( + <div className="flex items-center gap-1"> + <Badge variant={count > 1 ? "default" : "outline"} className="font-mono"> + {count}개 + </Badge> + {count > 1 && aggregatedRow.divisions && ( + <TooltipProvider> + <Tooltip> + <TooltipTrigger> + <div className="text-xs text-muted-foreground cursor-help"> + ({aggregatedRow.divisions.replace(',', ', ')}) + </div> + </TooltipTrigger> + <TooltipContent> + <p>{aggregatedRow.divisions.replace(',', ', ')} 평가의 평균값</p> + </TooltipContent> + </Tooltip> + </TooltipProvider> + )} + </div> + ); + }, + size: 100, + meta: { + excelHeader: "평가수", + }, + }] : []), { accessorKey: "finalScore", header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="확정점수" />, cell: ({ row }) => { const finalScore = row.getValue<number>("finalScore"); + const isAggregated = viewMode === "aggregated" && (row.original as PeriodicEvaluationAggregatedView).evaluationCount > 1; + return finalScore ? ( - <span className="font-bold text-green-600">{Number(finalScore).toFixed(1)}</span> + <div className="flex items-center gap-1"> + <span className={`font-bold ${isAggregated ? 'text-purple-600' : 'text-green-600'}`}> + {Number(finalScore).toFixed(1)} + </span> + {isAggregated && ( + <TooltipProvider> + <Tooltip> + <TooltipTrigger> + <Badge variant="outline" className="text-xs bg-purple-50">평균</Badge> + </TooltipTrigger> + <TooltipContent> + <p>여러 평가의 평균값</p> + </TooltipContent> + </Tooltip> + </TooltipProvider> + )} + </div> ) : ( <span className="text-muted-foreground">-</span> ); }, - size: 90, + size: viewMode === "aggregated" ? 120 : 90, + meta: { + excelHeader: "확정점수", + }, }, { @@ -285,8 +371,13 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="확정등급" />, cell: ({ row }) => { const finalGrade = row.getValue<string>("finalGrade"); + const isAggregated = viewMode === "aggregated" && (row.original as PeriodicEvaluationAggregatedView).evaluationCount > 1; + return finalGrade ? ( - <Badge variant={getGradeBadgeVariant(finalGrade)} className="bg-green-600"> + <Badge + variant={getGradeBadgeVariant(finalGrade)} + className={isAggregated ? "bg-purple-600" : "bg-green-600"} + > {finalGrade} </Badge> ) : ( @@ -294,10 +385,13 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): ); }, size: 90, + meta: { + excelHeader: "확정등급", + }, }, - // ═══════════════════════════════════════════════════════════════ - // 진행 현황 + // ═══════════════════════════════════════════════════════════════ + // 진행 현황 - 집계 모드에서는 최고 진행 상태를 보여줌 // ═══════════════════════════════════════════════════════════════ { header: "부서별 평가 현황", @@ -307,6 +401,9 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="발주" />, cell: ({ row }) => getDepartmentStatusBadge(row.getValue("orderEvalStatus")), size: 60, + meta: { + excelHeader: "발주", + }, }, { @@ -314,6 +411,9 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="조달" />, cell: ({ row }) => getDepartmentStatusBadge(row.getValue("procurementEvalStatus")), size: 70, + meta: { + excelHeader: "조달", + }, }, { @@ -321,6 +421,9 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="품질" />, cell: ({ row }) => getDepartmentStatusBadge(row.getValue("qualityEvalStatus")), size: 70, + meta: { + excelHeader: "품질", + }, }, { @@ -328,6 +431,9 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="설계" />, cell: ({ row }) => getDepartmentStatusBadge(row.getValue("designEvalStatus")), size: 70, + meta: { + excelHeader: "설계", + }, }, { @@ -335,13 +441,24 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="CS" />, cell: ({ row }) => getDepartmentStatusBadge(row.getValue("csEvalStatus")), size: 70, + meta: { + excelHeader: "CS", + }, + }, + + { + accessorKey: "adminEvalStatus", + header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="관리자" />, + cell: ({ row }) => getDepartmentStatusBadge(row.getValue("adminEvalStatus")), + size: 120, + meta: { + excelHeader: "관리자", + }, }, ] }, { - // id: "평가상세", - // accessorKey: "평가상세", header: "평가상세", enableHiding: true, size: 80, @@ -359,11 +476,11 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): > <Ellipsis className="size-4" /> </Button> - </div> ); }, }, + // ═══════════════════════════════════════════════════════════════ // 제출 현황 // ═══════════════════════════════════════════════════════════════ @@ -375,13 +492,32 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="문서제출" />, cell: ({ row }) => { const submitted = row.getValue<boolean>("documentsSubmitted"); + const isAggregated = viewMode === "aggregated" && (row.original as PeriodicEvaluationAggregatedView).evaluationCount > 1; + return ( - <Badge variant={submitted ? "default" : "destructive"}> - {submitted ? "제출완료" : "미제출"} - </Badge> + <div className="flex items-center gap-1"> + <Badge variant={submitted ? "default" : "destructive"}> + {submitted ? "제출완료" : "미제출"} + </Badge> + {isAggregated && ( + <TooltipProvider> + <Tooltip> + <TooltipTrigger> + <Badge variant="outline" className="text-xs">통합</Badge> + </TooltipTrigger> + <TooltipContent> + <p>모든 평가에서 제출 완료된 경우만 "제출완료"</p> + </TooltipContent> + </Tooltip> + </TooltipProvider> + )} + </div> ); }, - size: 120, + size: viewMode === "aggregated" ? 140 : 120, + meta: { + excelHeader: "문서제출", + }, }, { @@ -389,18 +525,37 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="제출일" />, cell: ({ row }) => { const submissionDate = row.getValue<Date>("submissionDate"); + const isAggregated = viewMode === "aggregated" && (row.original as PeriodicEvaluationAggregatedView).evaluationCount > 1; + return submissionDate ? ( - <span className="text-sm"> - {new Intl.DateTimeFormat("ko-KR", { - month: "2-digit", - day: "2-digit", - }).format(new Date(submissionDate))} - </span> + <div className="flex items-center gap-1"> + <span className="text-sm"> + {new Intl.DateTimeFormat("ko-KR", { + month: "2-digit", + day: "2-digit", + }).format(new Date(submissionDate))} + </span> + {isAggregated && ( + <TooltipProvider> + <Tooltip> + <TooltipTrigger> + <Badge variant="outline" className="text-xs">최신</Badge> + </TooltipTrigger> + <TooltipContent> + <p>가장 최근 제출일</p> + </TooltipContent> + </Tooltip> + </TooltipProvider> + )} + </div> ) : ( <span className="text-muted-foreground">-</span> ); }, - size: 80, + size: viewMode === "aggregated" ? 110 : 80, + meta: { + excelHeader: "제출일", + }, }, { @@ -423,30 +578,38 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): ); }, size: 80, + meta: { + excelHeader: "마감일", + }, }, ] }, - - // ═══════════════════════════════════════════════════════════════ - // 평가 점수 + // 평가 점수 - 집계 모드에서는 평균임을 명시 // ═══════════════════════════════════════════════════════════════ { - header: "평가 점수", + header: viewMode === "aggregated" ? "평가 점수 (평균)" : "평가 점수", columns: [ { accessorKey: "processScore", header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="공정" />, cell: ({ row }) => { const score = row.getValue("processScore"); + const isAggregated = viewMode === "aggregated" && (row.original as PeriodicEvaluationAggregatedView).evaluationCount > 1; + return score ? ( - <span className="font-medium">{Number(score).toFixed(1)}</span> + <span className={`font-medium ${isAggregated ? 'text-purple-600' : ''}`}> + {Number(score).toFixed(1)} + </span> ) : ( <span className="text-muted-foreground">-</span> ); }, size: 80, + meta: { + excelHeader: "공정", + }, }, { @@ -454,13 +617,20 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="가격" />, cell: ({ row }) => { const score = row.getValue("priceScore"); + const isAggregated = viewMode === "aggregated" && (row.original as PeriodicEvaluationAggregatedView).evaluationCount > 1; + return score ? ( - <span className="font-medium">{Number(score).toFixed(1)}</span> + <span className={`font-medium ${isAggregated ? 'text-purple-600' : ''}`}> + {Number(score).toFixed(1)} + </span> ) : ( <span className="text-muted-foreground">-</span> ); }, size: 80, + meta: { + excelHeader: "가격", + }, }, { @@ -468,13 +638,20 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="납기" />, cell: ({ row }) => { const score = row.getValue("deliveryScore"); + const isAggregated = viewMode === "aggregated" && (row.original as PeriodicEvaluationAggregatedView).evaluationCount > 1; + return score ? ( - <span className="font-medium">{Number(score).toFixed(1)}</span> + <span className={`font-medium ${isAggregated ? 'text-purple-600' : ''}`}> + {Number(score).toFixed(1)} + </span> ) : ( <span className="text-muted-foreground">-</span> ); }, size: 80, + meta: { + excelHeader: "납기", + }, }, { @@ -482,13 +659,20 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="자율평가" />, cell: ({ row }) => { const score = row.getValue("selfEvaluationScore"); + const isAggregated = viewMode === "aggregated" && (row.original as PeriodicEvaluationAggregatedView).evaluationCount > 1; + return score ? ( - <span className="font-medium">{Number(score).toFixed(1)}</span> + <span className={`font-medium ${isAggregated ? 'text-purple-600' : ''}`}> + {Number(score).toFixed(1)} + </span> ) : ( <span className="text-muted-foreground">-</span> ); }, size: 80, + meta: { + excelHeader: "자율평가", + }, }, // ✅ 합계 - 4개 점수의 합으로 계산 @@ -502,9 +686,12 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): const selfEvaluationScore = Number(row.getValue("selfEvaluationScore") || 0); const total = processScore + priceScore + deliveryScore + selfEvaluationScore; + const isAggregated = viewMode === "aggregated" && (row.original as PeriodicEvaluationAggregatedView).evaluationCount > 1; return total > 0 ? ( - <span className="font-medium bg-blue-50 px-2 py-1 rounded"> + <span className={`font-medium px-2 py-1 rounded ${ + isAggregated ? 'bg-purple-50 text-purple-600' : 'bg-blue-50 text-blue-600' + }`}> {total.toFixed(1)} </span> ) : ( @@ -512,6 +699,9 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): ); }, size: 80, + meta: { + excelHeader: "합계", + }, }, { @@ -519,13 +709,20 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="참여도(가점)" />, cell: ({ row }) => { const score = row.getValue("participationBonus"); + const isAggregated = viewMode === "aggregated" && (row.original as PeriodicEvaluationAggregatedView).evaluationCount > 1; + return score ? ( - <span className="font-medium text-green-600">+{Number(score).toFixed(1)}</span> + <span className={`font-medium ${isAggregated ? 'text-purple-600' : 'text-green-600'}`}> + +{Number(score).toFixed(1)} + </span> ) : ( <span className="text-muted-foreground">-</span> ); }, size: 100, + meta: { + excelHeader: "참여도(가점)", + }, }, { @@ -533,16 +730,23 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="품질(감점)" />, cell: ({ row }) => { const score = row.getValue("qualityDeduction"); + const isAggregated = viewMode === "aggregated" && (row.original as PeriodicEvaluationAggregatedView).evaluationCount > 1; + return score ? ( - <span className="font-medium text-red-600">-{Number(score).toFixed(1)}</span> + <span className={`font-medium ${isAggregated ? 'text-purple-600' : 'text-red-600'}`}> + -{Number(score).toFixed(1)} + </span> ) : ( <span className="text-muted-foreground">-</span> ); }, size: 100, + meta: { + excelHeader: "품질(감점)", + }, }, - // ✅ 새로운 평가점수 컬럼 추가 + // ✅ 평가점수 컬럼 { id: "evaluationScore", header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="평가점수" />, @@ -556,9 +760,12 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): const totalScore = processScore + priceScore + deliveryScore + selfEvaluationScore; const evaluationScore = totalScore + participationBonus - qualityDeduction; + const isAggregated = viewMode === "aggregated" && (row.original as PeriodicEvaluationAggregatedView).evaluationCount > 1; return totalScore > 0 ? ( - <span className="font-bold text-blue-600 bg-blue-50 px-2 py-1 rounded"> + <span className={`font-bold px-2 py-1 rounded ${ + isAggregated ? 'bg-purple-50 text-purple-600' : 'bg-blue-50 text-blue-600' + }`}> {evaluationScore.toFixed(1)} </span> ) : ( @@ -566,6 +773,9 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): ); }, size: 90, + meta: { + excelHeader: "평가점수", + }, }, { @@ -573,16 +783,27 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps): header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="평가등급" />, cell: ({ row }) => { const grade = row.getValue<string>("evaluationGrade"); + const isAggregated = viewMode === "aggregated" && (row.original as PeriodicEvaluationAggregatedView).evaluationCount > 1; + return grade ? ( - <Badge variant={getGradeBadgeVariant(grade)}>{grade}</Badge> + <Badge + variant={getGradeBadgeVariant(grade)} + className={isAggregated ? "bg-purple-600" : ""} + > + {grade} + </Badge> ) : ( <span className="text-muted-foreground">-</span> ); }, minSize: 100, + meta: { + excelHeader: "평가등급", + }, }, - ] }, ]; + + return baseColumns; }
\ No newline at end of file |
