summaryrefslogtreecommitdiff
path: root/lib/evaluation/table/evaluation-columns.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/evaluation/table/evaluation-columns.tsx')
-rw-r--r--lib/evaluation/table/evaluation-columns.tsx341
1 files changed, 232 insertions, 109 deletions
diff --git a/lib/evaluation/table/evaluation-columns.tsx b/lib/evaluation/table/evaluation-columns.tsx
index 821e8182..10aa7704 100644
--- a/lib/evaluation/table/evaluation-columns.tsx
+++ b/lib/evaluation/table/evaluation-columns.tsx
@@ -144,14 +144,14 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps):
},
// ░░░ 평가기간 ░░░
- {
- accessorKey: "evaluationPeriod",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="평가기간" />,
- cell: ({ row }) => (
- <Badge variant="outline">{row.getValue("evaluationPeriod")}</Badge>
- ),
- size: 100,
- },
+ // {
+ // accessorKey: "evaluationPeriod",
+ // header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="평가기간" />,
+ // cell: ({ row }) => (
+ // <Badge variant="outline">{row.getValue("evaluationPeriod")}</Badge>
+ // ),
+ // size: 100,
+ // },
// ░░░ 구분 ░░░
{
@@ -202,12 +202,113 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps):
},
]
},
+
+ {
+ accessorKey: "finalScore",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="확정점수" />,
+ cell: ({ row }) => {
+ const finalScore = row.getValue<number>("finalScore");
+ return finalScore ? (
+ <span className="font-bold text-green-600">{finalScore.toFixed(1)}</span>
+ ) : (
+ <span className="text-muted-foreground">-</span>
+ );
+ },
+ size: 90,
+ },
+ {
+ accessorKey: "finalGrade",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="확정등급" />,
+ cell: ({ row }) => {
+ const finalGrade = row.getValue<string>("finalGrade");
+ return finalGrade ? (
+ <Badge variant={getGradeBadgeVariant(finalGrade)} className="bg-green-600">
+ {finalGrade}
+ </Badge>
+ ) : (
+ <span className="text-muted-foreground">-</span>
+ );
+ },
+ size: 90,
+ },
+
+ // ═══════════════════════════════════════════════════════════════
+ // 진행 현황
+ // ═══════════════════════════════════════════════════════════════
+ {
+ header: "평가자 진행 현황",
+ columns: [
+ {
+ accessorKey: "status",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="진행상태" />,
+ cell: ({ row }) => {
+ const status = row.getValue<string>("status");
+ return (
+ <Badge variant={getStatusBadgeVariant(status)}>
+ {getStatusLabel(status)}
+ </Badge>
+ );
+ },
+ size: 100,
+ },
+
+ {
+ id: "reviewProgress",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="리뷰진행" />,
+ cell: ({ row }) => {
+ const totalReviewers = row.original.totalReviewers || 0;
+ const completedReviewers = row.original.completedReviewers || 0;
+
+ return getProgressBadge(completedReviewers, totalReviewers);
+ },
+ size: 120,
+ },
+
+ {
+ accessorKey: "reviewCompletedAt",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="검토완료일" />,
+ cell: ({ row }) => {
+ const completedAt = row.getValue<Date>("reviewCompletedAt");
+ return completedAt ? (
+ <span className="text-sm">
+ {new Intl.DateTimeFormat("ko-KR", {
+ month: "2-digit",
+ day: "2-digit",
+ }).format(new Date(completedAt))}
+ </span>
+ ) : (
+ <span className="text-muted-foreground">-</span>
+ );
+ },
+ size: 100,
+ },
+
+ {
+ accessorKey: "finalizedAt",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="확정일" />,
+ cell: ({ row }) => {
+ const finalizedAt = row.getValue<Date>("finalizedAt");
+ return finalizedAt ? (
+ <span className="text-sm font-medium">
+ {new Intl.DateTimeFormat("ko-KR", {
+ month: "2-digit",
+ day: "2-digit",
+ }).format(new Date(finalizedAt))}
+ </span>
+ ) : (
+ <span className="text-muted-foreground">-</span>
+ );
+ },
+ size: 80,
+ },
+ ]
+ },
// ═══════════════════════════════════════════════════════════════
// 제출 현황
// ═══════════════════════════════════════════════════════════════
{
- header: "제출 현황",
+ header: "협력업체 제출 현황",
columns: [
{
accessorKey: "documentsSubmitted",
@@ -266,6 +367,8 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps):
]
},
+
+
// ═══════════════════════════════════════════════════════════════
// 평가 점수
// ═══════════════════════════════════════════════════════════════
@@ -273,12 +376,12 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps):
header: "평가 점수",
columns: [
{
- accessorKey: "totalScore",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="총점" />,
+ accessorKey: "processScore",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="공정" />,
cell: ({ row }) => {
- const score = row.getValue<number>("totalScore");
+ const score = row.getValue("processScore");
return score ? (
- <span className="font-medium">{score.toFixed(1)}</span>
+ <span className="font-medium">{Number(score).toFixed(1)}</span>
) : (
<span className="text-muted-foreground">-</span>
);
@@ -287,156 +390,176 @@ export function getPeriodicEvaluationsColumns({setRowAction}: GetColumnsProps):
},
{
- accessorKey: "evaluationGrade",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="등급" />,
+ accessorKey: "priceScore",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="가격" />,
cell: ({ row }) => {
- const grade = row.getValue<string>("evaluationGrade");
- return grade ? (
- <Badge variant={getGradeBadgeVariant(grade)}>{grade}</Badge>
+ const score = row.getValue("priceScore");
+ return score ? (
+ <span className="font-medium">{Number(score).toFixed(1)}</span>
) : (
<span className="text-muted-foreground">-</span>
);
},
- size: 60,
+ size: 80,
},
-
+
{
- accessorKey: "finalScore",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="최종점수" />,
+ accessorKey: "deliveryScore",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="납기" />,
cell: ({ row }) => {
- const finalScore = row.getValue<number>("finalScore");
- return finalScore ? (
- <span className="font-bold text-green-600">{finalScore.toFixed(1)}</span>
+ const score = row.getValue("deliveryScore");
+ return score ? (
+ <span className="font-medium">{Number(score).toFixed(1)}</span>
) : (
<span className="text-muted-foreground">-</span>
);
},
- size: 90,
+ size: 80,
+ },
+
+ {
+ accessorKey: "selfEvaluationScore",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="자율평가" />,
+ cell: ({ row }) => {
+ const score = row.getValue("selfEvaluationScore");
+ return score ? (
+ <span className="font-medium">{Number(score).toFixed(1)}</span>
+ ) : (
+ <span className="text-muted-foreground">-</span>
+ );
+ },
+ size: 80,
},
+ // ✅ 합계 - 4개 점수의 합으로 계산
{
- accessorKey: "finalGrade",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="최종등급" />,
+ id: "totalScore",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="합계" />,
cell: ({ row }) => {
- const finalGrade = row.getValue<string>("finalGrade");
- return finalGrade ? (
- <Badge variant={getGradeBadgeVariant(finalGrade)} className="bg-green-600">
- {finalGrade}
- </Badge>
+ const processScore = Number(row.getValue("processScore") || 0);
+ const priceScore = Number(row.getValue("priceScore") || 0);
+ const deliveryScore = Number(row.getValue("deliveryScore") || 0);
+ const selfEvaluationScore = Number(row.getValue("selfEvaluationScore") || 0);
+
+ const total = processScore + priceScore + deliveryScore + selfEvaluationScore;
+
+ return total > 0 ? (
+ <span className="font-medium bg-blue-50 px-2 py-1 rounded">
+ {total.toFixed(1)}
+ </span>
) : (
<span className="text-muted-foreground">-</span>
);
},
- size: 90,
+ size: 80,
},
- ]
- },
- // ═══════════════════════════════════════════════════════════════
- // 진행 현황
- // ═══════════════════════════════════════════════════════════════
- {
- header: "진행 현황",
- columns: [
{
- accessorKey: "status",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="진행상태" />,
+ accessorKey: "participationBonus",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="참여도(가점)" />,
cell: ({ row }) => {
- const status = row.getValue<string>("status");
- return (
- <Badge variant={getStatusBadgeVariant(status)}>
- {getStatusLabel(status)}
- </Badge>
+ const score = row.getValue("participationBonus");
+ return score ? (
+ <span className="font-medium text-green-600">+{Number(score).toFixed(1)}</span>
+ ) : (
+ <span className="text-muted-foreground">-</span>
);
},
size: 100,
},
{
- id: "reviewProgress",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="리뷰진행" />,
+ accessorKey: "qualityDeduction",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="품질(감점)" />,
cell: ({ row }) => {
- const totalReviewers = row.original.totalReviewers || 0;
- const completedReviewers = row.original.completedReviewers || 0;
-
- return getProgressBadge(completedReviewers, totalReviewers);
+ const score = row.getValue("qualityDeduction");
+ return score ? (
+ <span className="font-medium text-red-600">-{Number(score).toFixed(1)}</span>
+ ) : (
+ <span className="text-muted-foreground">-</span>
+ );
},
- size: 120,
+ size: 100,
},
+ // ✅ 새로운 평가점수 컬럼 추가
{
- accessorKey: "reviewCompletedAt",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="검토완료일" />,
+ id: "evaluationScore",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="평가점수" />,
cell: ({ row }) => {
- const completedAt = row.getValue<Date>("reviewCompletedAt");
- return completedAt ? (
- <span className="text-sm">
- {new Intl.DateTimeFormat("ko-KR", {
- month: "2-digit",
- day: "2-digit",
- }).format(new Date(completedAt))}
+ const processScore = Number(row.getValue("processScore") || 0);
+ const priceScore = Number(row.getValue("priceScore") || 0);
+ const deliveryScore = Number(row.getValue("deliveryScore") || 0);
+ const selfEvaluationScore = Number(row.getValue("selfEvaluationScore") || 0);
+ const participationBonus = Number(row.getValue("participationBonus") || 0);
+ const qualityDeduction = Number(row.getValue("qualityDeduction") || 0);
+
+ const totalScore = processScore + priceScore + deliveryScore + selfEvaluationScore;
+ const evaluationScore = totalScore + participationBonus - qualityDeduction;
+
+ return totalScore > 0 ? (
+ <span className="font-bold text-blue-600 bg-blue-50 px-2 py-1 rounded">
+ {evaluationScore.toFixed(1)}
</span>
) : (
<span className="text-muted-foreground">-</span>
);
},
- size: 100,
+ size: 90,
},
{
- accessorKey: "finalizedAt",
- header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="확정일" />,
+ accessorKey: "evaluationGrade",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="평가등급" />,
cell: ({ row }) => {
- const finalizedAt = row.getValue<Date>("finalizedAt");
- return finalizedAt ? (
- <span className="text-sm font-medium">
- {new Intl.DateTimeFormat("ko-KR", {
- month: "2-digit",
- day: "2-digit",
- }).format(new Date(finalizedAt))}
- </span>
+ const grade = row.getValue<string>("evaluationGrade");
+ return grade ? (
+ <Badge variant={getGradeBadgeVariant(grade)}>{grade}</Badge>
) : (
<span className="text-muted-foreground">-</span>
);
},
size: 80,
},
+
]
},
+
+
// ░░░ Actions ░░░
- {
- id: "actions",
- enableHiding: false,
- size: 40,
- minSize: 40,
- cell: ({ row }) => {
- return (
- <div className="flex items-center gap-1">
- <Button
- variant="ghost"
- size="icon"
- className="size-8"
- onClick={() => setRowAction({ row, type: "view" })}
- aria-label="상세보기"
- title="상세보기"
- >
- <Eye className="size-4" />
- </Button>
-
- <Button
- variant="ghost"
- size="icon"
- className="size-8"
- onClick={() => setRowAction({ row, type: "update" })}
- aria-label="수정"
- title="수정"
- >
- <Pencil className="size-4" />
- </Button>
- </div>
- );
- },
- },
+ // {
+ // id: "actions",
+ // enableHiding: false,
+ // size: 40,
+ // minSize: 40,
+ // cell: ({ row }) => {
+ // return (
+ // <div className="flex items-center gap-1">
+ // <Button
+ // variant="ghost"
+ // size="icon"
+ // className="size-8"
+ // onClick={() => setRowAction({ row, type: "view" })}
+ // aria-label="상세보기"
+ // title="상세보기"
+ // >
+ // <Eye className="size-4" />
+ // </Button>
+
+ // <Button
+ // variant="ghost"
+ // size="icon"
+ // className="size-8"
+ // onClick={() => setRowAction({ row, type: "update" })}
+ // aria-label="수정"
+ // title="수정"
+ // >
+ // <Pencil className="size-4" />
+ // </Button>
+ // </div>
+ // );
+ // },
+ // },
];
} \ No newline at end of file