From 90f79a7a691943a496f67f01c1e493256070e4de Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 7 Jul 2025 01:44:45 +0000 Subject: (대표님) 변경사항 20250707 10시 43분 - unstaged 변경사항 추가 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../table/evaluation-submissions-table-columns.tsx | 556 +++++++++++++++++++++ 1 file changed, 556 insertions(+) create mode 100644 lib/evaluation-submit/table/evaluation-submissions-table-columns.tsx (limited to 'lib/evaluation-submit/table/evaluation-submissions-table-columns.tsx') diff --git a/lib/evaluation-submit/table/evaluation-submissions-table-columns.tsx b/lib/evaluation-submit/table/evaluation-submissions-table-columns.tsx new file mode 100644 index 00000000..1ec0284f --- /dev/null +++ b/lib/evaluation-submit/table/evaluation-submissions-table-columns.tsx @@ -0,0 +1,556 @@ +"use client" + +import * as React from "react" +import { type DataTableRowAction } from "@/types/table" +import { type ColumnDef } from "@tanstack/react-table" +import { + Ellipsis, + InfoIcon, + PenToolIcon, + FileTextIcon, + ClipboardListIcon, + CheckIcon, + XIcon, + ClockIcon, + Send, + User, + Calendar +} from "lucide-react" + +import { formatDate, formatCurrency } from "@/lib/utils" +import { Button } from "@/components/ui/button" +import { Checkbox } from "@/components/ui/checkbox" +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { Badge } from "@/components/ui/badge" +import { useRouter } from "next/navigation" + +import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" +import { ReviewerEvaluationView } from "@/db/schema" + + +type NextRouter = ReturnType; + +interface GetColumnsProps { + setRowAction: React.Dispatch | null>> + router: NextRouter; + +} + +/** + * 평가 진행 상태에 따른 배지 스타일 + */ +const getProgressBadge = (isCompleted: boolean, completedAt: Date | null) => { + if (isCompleted && completedAt) { + return { + variant: "default" as const, + icon: , + label: "완료", + className: "bg-green-100 text-green-800 border-green-200" + } + } else { + return { + variant: "secondary" as const, + icon: , + label: "미완료" + } + } +} + +/** + * 정기평가 상태에 따른 배지 스타일 + */ +const getPeriodicStatusBadge = (status: string) => { + switch (status) { + case 'PENDING': + return { + variant: "secondary" as const, + icon: , + label: "대기중" + } + + case 'PENDING_SUBMISSION': + return { + variant: "secondary" as const, + icon: , + label: "업체 제출 대기중" + } + case 'IN_PROGRESS': + return { + variant: "default" as const, + icon: , + label: "진행중" + } + case 'REVIEW': + return { + variant: "outline" as const, + icon: , + label: "검토중" + } + case 'COMPLETED': + return { + variant: "default" as const, + icon: , + label: "완료", + className: "bg-green-100 text-green-800 border-green-200" + } + default: + return { + variant: "secondary" as const, + icon: null, + label: status + } + } +} + +/** + * 평가 제출 테이블 컬럼 정의 + */ +export function getColumns({ setRowAction, router }: GetColumnsProps): ColumnDef[] { + + // ---------------------------------------------------------------- + // 1) select 컬럼 (체크박스) + // ---------------------------------------------------------------- + const selectColumn: ColumnDef = { + id: "select", + header: ({ table }) => ( + table.toggleAllPageRowsSelected(!!value)} + aria-label="Select all" + className="translate-y-0.5" + /> + ), + cell: ({ row }) => ( + row.toggleSelected(!!value)} + aria-label="Select row" + className="translate-y-0.5" + /> + ), + enableSorting: false, + enableHiding: false, + size: 40, + } + + // ---------------------------------------------------------------- + // 2) 기본 정보 컬럼들 + // ---------------------------------------------------------------- + const basicColumns: ColumnDef[] = [ + { + accessorKey: "evaluationYear", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( + + {row.getValue("evaluationYear")}년 + + ), + size: 80, + }, + + { + id: "vendorInfo", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const vendorName = row.original.vendorName; + const vendorCode = row.original.vendorCode; + const domesticForeign = row.original.domesticForeign; + + return ( +
+
{vendorName}
+
+ {vendorCode} • {domesticForeign === 'DOMESTIC' ? 'D' : 'F'} +
+
+ ); + }, + enableSorting: false, + size: 200, + }, + + + { + id: "materialType", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const materialType = row.original.materialType; + const material = materialType ==="BULK" ? "벌크": materialType ==="EQUIPMENT" ? "기자재" :"기자재/벌크" + + return ( +
+
{material}
+ +
+ ); + }, + enableSorting: false, + }, + + { + id: "division", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const division = row.original.division; + const divisionKR = division === "PLANT"?"해양":"조선"; + + return ( +
+
{divisionKR}
+ +
+ ); + }, + enableSorting: false, + }, + ] + + // ---------------------------------------------------------------- + // 3) 상태 정보 컬럼들 + // ---------------------------------------------------------------- + const statusColumns: ColumnDef[] = [ + { + id: "evaluationProgress", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const isCompleted = row.original.isCompleted; + const completedAt = row.original.completedAt; + const badgeInfo = getProgressBadge(isCompleted, completedAt); + + return ( +
+ + {badgeInfo.icon} + {badgeInfo.label} + + {completedAt && ( +
+ {formatDate(completedAt,"KR")} +
+ )} +
+ ); + }, + size: 130, + }, + + { + id: "periodicStatus", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const status = row.original.periodicStatus; + const badgeInfo = getPeriodicStatusBadge(status); + + return ( + + {badgeInfo.icon} + {badgeInfo.label} + + ); + }, + size: 120, + }, + + // { + // id: "submissionInfo", + // header: ({ column }) => ( + // + // ), + // cell: ({ row }) => { + // // const submissionDate = row.original.submittedAt; + // const completedAt = row.original.completedAt; + + // return ( + //
+ //
+ // + // {submissionDate ? "제출완료" : "미제출"} + // + //
+ + // {completedAt && ( + //
+ // 평가완료: {formatDate(completedAt, "KR")} + //
+ // )} + // {/* {submissionDate && ( + //
+ // 제출: {formatDate(submissionDate, "KR")} + //
+ // )} */} + + //
+ // ); + // }, + // enableSorting: false, + // size: 140, + // }, + ] + + // ---------------------------------------------------------------- + // 4) 점수 및 평가 정보 컬럼들 + // ---------------------------------------------------------------- + const scoreColumns: ColumnDef[] = [ + { + id: "periodicScores", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const finalScore = row.original.periodicFinalScore; + const finalGrade = row.original.periodicFinalGrade; + const evaluationScore = row.original.periodicEvaluationScore; + const evaluationGrade = row.original.periodicEvaluationGrade; + + return ( +
+ {finalScore && finalGrade ? ( +
+
+ 최종: {parseFloat(finalScore.toString()).toFixed(1)}점 +
+ {finalGrade} +
+ ) : evaluationScore && evaluationGrade ? ( +
+
+ {parseFloat(evaluationScore.toString()).toFixed(1)}점 +
+ {evaluationGrade} +
+ ) : ( + 미산정 + )} +
+ ); + }, + enableSorting: false, + size: 120, + }, + + ] + + + + // ---------------------------------------------------------------- + // 6) 메타데이터 컬럼들 + // ---------------------------------------------------------------- + const metaColumns: ColumnDef[] = [ + { + accessorKey: "reviewerEvaluationCreatedAt", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const date = row.getValue("reviewerEvaluationCreatedAt") as Date; + return formatDate(date); + }, + size: 140, + }, + { + accessorKey: "reviewerEvaluationUpdatedAt", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const date = row.getValue("reviewerEvaluationUpdatedAt") as Date; + return formatDate(date); + }, + size: 140, + }, + ] + + // ---------------------------------------------------------------- + // 7) actions 컬럼 (드롭다운 메뉴) + // ---------------------------------------------------------------- + const actionsColumn: ColumnDef = { + id: "actions", + header: "작업", + enableHiding: false, + cell: function Cell({ row }) { + const isCompleted = row.original.isCompleted; + const reviewerEvaluationId = row.original.reviewerEvaluationId; + + return ( + + + + + + router.push(`/evcp/evaluation-input/${reviewerEvaluationId}`)} + > + {isCompleted ? "완료된 평가보기":"평가 작성하기"} + + + + + ) + }, + size: 80, + } + + // ---------------------------------------------------------------- + // 8) 최종 컬럼 배열 + // ---------------------------------------------------------------- + return [ + selectColumn, + ...basicColumns, + { + id: "statusInfo", + header: "상태 정보", + columns: statusColumns, + }, + { + id: "scoreInfo", + header: "점수 및 평가", + columns: scoreColumns, + }, + + { + id: "metadata", + header: "메타데이터", + columns: metaColumns, + }, + actionsColumn, + ] +} + +// ---------------------------------------------------------------- +// 9) 컬럼 설정 (필터링용) +// ---------------------------------------------------------------- +export const evaluationSubmissionsColumnsConfig = [ + { + id: "reviewerEvaluationId", + label: "평가 ID", + group: "기본 정보", + type: "text", + excelHeader: "Evaluation ID", + }, + { + id: "vendorName", + label: "협력업체명", + group: "기본 정보", + type: "text", + excelHeader: "Vendor Name", + }, + { + id: "vendorCode", + label: "협력업체 코드", + group: "기본 정보", + type: "text", + excelHeader: "Vendor Code", + }, + { + id: "evaluationYear", + label: "평가연도", + group: "기본 정보", + type: "number", + excelHeader: "Evaluation Year", + }, + { + id: "departmentCode", + label: "부서코드", + group: "기본 정보", + type: "text", + excelHeader: "Department Code", + }, + { + id: "isCompleted", + label: "완료 여부", + group: "상태 정보", + type: "select", + options: [ + { label: "완료", value: "true" }, + { label: "미완료", value: "false" }, + ], + excelHeader: "Is Completed", + }, + { + id: "periodicStatus", + label: "정기평가 상태", + group: "상태 정보", + type: "select", + options: [ + { label: "대기중", value: "PENDING" }, + { label: "진행중", value: "IN_PROGRESS" }, + { label: "검토중", value: "REVIEW" }, + { label: "완료", value: "COMPLETED" }, + ], + excelHeader: "Periodic Status", + }, + { + id: "documentsSubmitted", + label: "문서 제출여부", + group: "상태 정보", + type: "select", + options: [ + { label: "제출완료", value: "true" }, + { label: "미제출", value: "false" }, + ], + excelHeader: "Documents Submitted", + }, + { + id: "periodicFinalScore", + label: "최종점수", + group: "점수 정보", + type: "number", + excelHeader: "Final Score", + }, + { + id: "periodicFinalGrade", + label: "최종등급", + group: "점수 정보", + type: "text", + excelHeader: "Final Grade", + }, + { + id: "reviewerEvaluationCreatedAt", + label: "생성일", + group: "메타데이터", + type: "date", + excelHeader: "Created At", + }, + { + id: "reviewerEvaluationUpdatedAt", + label: "수정일", + group: "메타데이터", + type: "date", + excelHeader: "Updated At", + }, +] as const; \ No newline at end of file -- cgit v1.2.3