From 4e63d8427d26d0d1b366ddc53650e15f3481fc75 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Tue, 24 Jun 2025 01:44:03 +0000 Subject: (대표님/최겸) 20250624 작업사항 10시43분 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../table/evaluation-targets-columns.tsx | 351 ++++++++------------- 1 file changed, 125 insertions(+), 226 deletions(-) (limited to 'lib/evaluation-target-list/table/evaluation-targets-columns.tsx') diff --git a/lib/evaluation-target-list/table/evaluation-targets-columns.tsx b/lib/evaluation-target-list/table/evaluation-targets-columns.tsx index 93807ef9..e2163cad 100644 --- a/lib/evaluation-target-list/table/evaluation-targets-columns.tsx +++ b/lib/evaluation-target-list/table/evaluation-targets-columns.tsx @@ -4,16 +4,17 @@ 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 } from "lucide-react"; +import { Pencil, Check, X } from "lucide-react"; import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"; import { EvaluationTargetWithDepartments } from "@/db/schema"; -import { EditEvaluationTargetSheet } from "./update-evaluation-target"; +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": @@ -27,7 +28,15 @@ const getStatusBadgeVariant = (status: string) => { } }; -// 의견 일치 여부 배지 +const getStatusText = (status: string) => { + const statusMap = { + PENDING: "검토 중", + CONFIRMED: "확정", + EXCLUDED: "제외" + }; + return statusMap[status] || status; +}; + const getConsensusBadge = (consensusStatus: boolean | null) => { if (consensusStatus === null) { return 검토 중; @@ -38,16 +47,14 @@ const getConsensusBadge = (consensusStatus: boolean | null) => { return 의견 불일치; }; -// 구분 배지 const getDivisionBadge = (division: string) => { return ( - - {division === "PLANT" ? "해양" : "조선"} + + {division === "OCEAN" ? "해양" : "조선"} ); }; -// 자재구분 배지 const getMaterialTypeBadge = (materialType: string) => { const typeMap = { EQUIPMENT: "기자재", @@ -57,7 +64,6 @@ const getMaterialTypeBadge = (materialType: string) => { return {typeMap[materialType] || materialType}; }; -// 내외자 배지 const getDomesticForeignBadge = (domesticForeign: string) => { return ( @@ -66,24 +72,27 @@ const getDomesticForeignBadge = (domesticForeign: string) => { ); }; -// 평가 상태 배지 -const getApprovalBadge = (isApproved: boolean | null) => { - if (isApproved === null) { - return 대기중; - } - if (isApproved === true) { - return 승인; +// ✅ 평가 대상 여부 표시 함수 +const getEvaluationTargetBadge = (isTarget: boolean | null) => { + if (isTarget === null) { + return 미정; } - return 거부; + return isTarget ? ( + + + 평가 대상 + + ) : ( + + + 평가 제외 + + ); }; -export function getEvaluationTargetsColumns({setRowAction}:GetColumnsProps): ColumnDef[] { +export function getEvaluationTargetsColumns({ setRowAction }: GetColumnsProps): ColumnDef[] { return [ - // ═══════════════════════════════════════════════════════════════ - // 기본 정보 - // ═══════════════════════════════════════════════════════════════ - - // Checkbox + // ✅ Checkbox { id: "select", header: ({ table }) => ( @@ -107,15 +116,13 @@ export function getEvaluationTargetsColumns({setRowAction}:GetColumnsProps): Col enableHiding: false, }, - // ░░░ 평가년도 ░░░ + // ✅ 기본 정보 { accessorKey: "evaluationYear", header: ({ column }) => , cell: ({ row }) => {row.getValue("evaluationYear")}, size: 100, }, - - // ░░░ 구분 ░░░ { accessorKey: "division", header: ({ column }) => , @@ -127,24 +134,25 @@ export function getEvaluationTargetsColumns({setRowAction}:GetColumnsProps): Col header: ({ column }) => , cell: ({ row }) => { const status = row.getValue("status"); - const statusMap = { - PENDING: "검토 중", - CONFIRMED: "확정", - EXCLUDED: "제외" - }; return ( - {statusMap[status] || status} + {getStatusText(status)} ); }, size: 100, }, + { + accessorKey: "consensusStatus", + header: ({ column }) => , + cell: ({ row }) => getConsensusBadge(row.getValue("consensusStatus")), + size: 100, + }, - // ░░░ 벤더 코드 ░░░ - + // ✅ 벤더 정보 그룹 { - header: "협력업체 정보", + id: "vendorInfo", + header: "벤더 정보", columns: [ { accessorKey: "vendorCode", @@ -154,8 +162,6 @@ export function getEvaluationTargetsColumns({setRowAction}:GetColumnsProps): Col ), size: 120, }, - - // ░░░ 벤더명 ░░░ { accessorKey: "vendorName", header: ({ column }) => , @@ -166,267 +172,182 @@ export function getEvaluationTargetsColumns({setRowAction}:GetColumnsProps): Col ), 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, + }, ] }, - // ░░░ 자재구분 ░░░ - { - accessorKey: "materialType", - header: ({ column }) => , - cell: ({ row }) => getMaterialTypeBadge(row.getValue("materialType")), - size: 120, - }, - - // ░░░ 상태 ░░░ - - - // ░░░ 의견 일치 여부 ░░░ - { - accessorKey: "consensusStatus", - header: ({ column }) => , - cell: ({ row }) => getConsensusBadge(row.getValue("consensusStatus")), - size: 100, - }, - - // ═══════════════════════════════════════════════════════════════ - // 주문 부서 그룹 - // ═══════════════════════════════════════════════════════════════ + // ✅ 발주 담당자 { - header: "발주 평가 담당자", + id: "orderReviewer", + header: "발주 담당자", columns: [ - { - accessorKey: "orderDepartmentName", - header: ({ column }) => , - cell: ({ row }) => { - const departmentName = row.getValue("orderDepartmentName"); - return departmentName ? ( -
- {departmentName} -
- ) : ( - - - ); - }, - size: 120, - }, { accessorKey: "orderReviewerName", - header: ({ column }) => , + header: ({ column }) => , cell: ({ row }) => { const reviewerName = row.getValue("orderReviewerName"); return reviewerName ? ( -
+
{reviewerName}
) : ( - ); }, - size: 100, + size: 120, }, { accessorKey: "orderIsApproved", - header: ({ column }) => , - cell: ({ row }) => getApprovalBadge(row.getValue("orderIsApproved")), - size: 80, + header: ({ column }) => , + cell: ({ row }) => { + const isApproved = row.getValue("orderIsApproved"); + return getEvaluationTargetBadge(isApproved); + }, + size: 120, }, - ], + ] }, - // ═══════════════════════════════════════════════════════════════ - // 조달 부서 그룹 - // ═══════════════════════════════════════════════════════════════ + // ✅ 조달 담당자 { - header: "조달 평가 담당자", + id: "procurementReviewer", + header: "조달 담당자", columns: [ - { - accessorKey: "procurementDepartmentName", - header: ({ column }) => , - cell: ({ row }) => { - const departmentName = row.getValue("procurementDepartmentName"); - return departmentName ? ( -
- {departmentName} -
- ) : ( - - - ); - }, - size: 120, - }, { accessorKey: "procurementReviewerName", - header: ({ column }) => , + header: ({ column }) => , cell: ({ row }) => { const reviewerName = row.getValue("procurementReviewerName"); return reviewerName ? ( -
+
{reviewerName}
) : ( - ); }, - size: 100, + size: 120, }, { accessorKey: "procurementIsApproved", - header: ({ column }) => , - cell: ({ row }) => getApprovalBadge(row.getValue("procurementIsApproved")), - size: 80, + header: ({ column }) => , + cell: ({ row }) => { + const isApproved = row.getValue("procurementIsApproved"); + return getEvaluationTargetBadge(isApproved); + }, + size: 120, }, - ], + ] }, - // ═══════════════════════════════════════════════════════════════ - // 품질 부서 그룹 - // ═══════════════════════════════════════════════════════════════ + // ✅ 품질 담당자 { - header: "품질 평가 담당자", + id: "qualityReviewer", + header: "품질 담당자", columns: [ - { - accessorKey: "qualityDepartmentName", - header: ({ column }) => , - cell: ({ row }) => { - const departmentName = row.getValue("qualityDepartmentName"); - return departmentName ? ( -
- {departmentName} -
- ) : ( - - - ); - }, - size: 120, - }, { accessorKey: "qualityReviewerName", - header: ({ column }) => , + header: ({ column }) => , cell: ({ row }) => { const reviewerName = row.getValue("qualityReviewerName"); return reviewerName ? ( -
+
{reviewerName}
) : ( - ); }, - size: 100, + size: 120, }, { accessorKey: "qualityIsApproved", - header: ({ column }) => , - cell: ({ row }) => getApprovalBadge(row.getValue("qualityIsApproved")), - size: 80, + header: ({ column }) => , + cell: ({ row }) => { + const isApproved = row.getValue("qualityIsApproved"); + return getEvaluationTargetBadge(isApproved); + }, + size: 120, }, - ], + ] }, - // ═══════════════════════════════════════════════════════════════ - // 설계 부서 그룹 - // ═══════════════════════════════════════════════════════════════ + // ✅ 설계 담당자 { - header: "설계 평가 담당자", + id: "designReviewer", + header: "설계 담당자", columns: [ - { - accessorKey: "designDepartmentName", - header: ({ column }) => , - cell: ({ row }) => { - const departmentName = row.getValue("designDepartmentName"); - return departmentName ? ( -
- {departmentName} -
- ) : ( - - - ); - }, - size: 120, - }, { accessorKey: "designReviewerName", - header: ({ column }) => , + header: ({ column }) => , cell: ({ row }) => { const reviewerName = row.getValue("designReviewerName"); return reviewerName ? ( -
+
{reviewerName}
) : ( - ); }, - size: 100, + size: 120, }, { accessorKey: "designIsApproved", - header: ({ column }) => , - cell: ({ row }) => getApprovalBadge(row.getValue("designIsApproved")), - size: 80, + header: ({ column }) => , + cell: ({ row }) => { + const isApproved = row.getValue("designIsApproved"); + return getEvaluationTargetBadge(isApproved); + }, + size: 120, }, - ], + ] }, - // ═══════════════════════════════════════════════════════════════ - // CS 부서 그룹 - // ═══════════════════════════════════════════════════════════════ + // ✅ CS 담당자 { - header: "CS 평가 담당자", + id: "csReviewer", + header: "CS 담당자", columns: [ - { - accessorKey: "csDepartmentName", - header: ({ column }) => , - cell: ({ row }) => { - const departmentName = row.getValue("csDepartmentName"); - return departmentName ? ( -
- {departmentName} -
- ) : ( - - - ); - }, - size: 120, - }, { accessorKey: "csReviewerName", - header: ({ column }) => , + header: ({ column }) => , cell: ({ row }) => { const reviewerName = row.getValue("csReviewerName"); return reviewerName ? ( -
+
{reviewerName}
) : ( - ); }, - size: 100, + size: 120, }, { accessorKey: "csIsApproved", - header: ({ column }) => , - cell: ({ row }) => getApprovalBadge(row.getValue("csIsApproved")), - size: 80, + header: ({ column }) => , + cell: ({ row }) => { + const isApproved = row.getValue("csIsApproved"); + return getEvaluationTargetBadge(isApproved); + }, + size: 120, }, - ], + ] }, - // ═══════════════════════════════════════════════════════════════ - // 관리 정보 - // ═══════════════════════════════════════════════════════════════ - - // ░░░ 관리자 의견 ░░░ + // ✅ 의견 및 결과 { accessorKey: "adminComment", header: ({ column }) => , @@ -442,8 +363,6 @@ export function getEvaluationTargetsColumns({setRowAction}:GetColumnsProps): Col }, size: 150, }, - - // ░░░ 종합 의견 ░░░ { accessorKey: "consolidatedComment", header: ({ column }) => , @@ -459,69 +378,49 @@ export function getEvaluationTargetsColumns({setRowAction}:GetColumnsProps): Col }, size: 150, }, - - // ░░░ 확정일 ░░░ { accessorKey: "confirmedAt", header: ({ column }) => , cell: ({ row }) => { const confirmedAt = row.getValue("confirmedAt"); - return confirmedAt ? ( - - {new Intl.DateTimeFormat("ko-KR", { - year: "numeric", - month: "2-digit", - day: "2-digit", - }).format(new Date(confirmedAt))} - - ) : ( - - - ); + return {formatDate(confirmedAt, "KR")}; }, size: 100, }, - - // ░░░ 생성일 ░░░ { accessorKey: "createdAt", header: ({ column }) => , cell: ({ row }) => { const createdAt = row.getValue("createdAt"); - return createdAt ? ( - - {new Intl.DateTimeFormat("ko-KR", { - year: "numeric", - month: "2-digit", - day: "2-digit", - }).format(new Date(createdAt))} - - ) : ( - - - ); + return {formatDate(createdAt, "KR")}; }, size: 100, }, - // ░░░ Actions ░░░ + // ✅ Actions - 가장 안전하게 처리 { id: "actions", enableHiding: false, size: 40, minSize: 40, cell: ({ row }) => { - return ( + // ✅ 함수를 직접 정의해서 매번 새로 생성되지 않도록 처리 + const handleEdit = () => { + setRowAction({ row, type: "update" }); + }; + + return (
-
); }, -- cgit v1.2.3