From 53ad72732f781e6c6d5ddb3776ea47aec010af8e Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 4 Aug 2025 09:39:21 +0000 Subject: (최겸) PQ/실사 수정 및 개발 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pq-review-table-new/vendors-table-columns.tsx | 1425 +++++++++++--------- 1 file changed, 786 insertions(+), 639 deletions(-) (limited to 'lib/pq/pq-review-table-new/vendors-table-columns.tsx') diff --git a/lib/pq/pq-review-table-new/vendors-table-columns.tsx b/lib/pq/pq-review-table-new/vendors-table-columns.tsx index 6bfa8c7f..d99f201e 100644 --- a/lib/pq/pq-review-table-new/vendors-table-columns.tsx +++ b/lib/pq/pq-review-table-new/vendors-table-columns.tsx @@ -1,640 +1,787 @@ -"use client" - -import * as React from "react" -import { type DataTableRowAction } from "@/types/table" -import { type ColumnDef } from "@tanstack/react-table" -import { Ellipsis, Eye, PaperclipIcon, FileEdit } from "lucide-react" - -import { formatDate } from "@/lib/utils" -import { Badge } from "@/components/ui/badge" -import { Button } from "@/components/ui/button" -import { Checkbox } from "@/components/ui/checkbox" -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu" -import { DataTableColumnHeader } from "@/components/data-table/data-table-column-header" -import { useRouter } from "next/navigation" - -// PQ 제출 타입 정의 -export interface PQSubmission { - id: number - pqNumber: string - type: string - status: string - requesterName: string | null // 요청자 이름 - createdAt: Date - updatedAt: Date - submittedAt: Date | null - approvedAt: Date | null - rejectedAt: Date | null - rejectReason: string | null - vendorId: number - vendorName: string - vendorCode: string - taxId: string - vendorStatus: string - projectId: number | null - projectName: string | null - projectCode: string | null - answerCount: number - attachmentCount: number - pqStatus: string - pqTypeLabel: string - investigation: { - id: number - investigationStatus: string - requesterName: string | null // 실사 요청자 이름 - evaluationType: "SITE_AUDIT" | "QM_SELF_AUDIT" | null - qmManagerId: number | null - qmManagerName: string | null // QM 담당자 이름 - qmManagerEmail: string | null // QM 담당자 이메일 - investigationAddress: string | null - investigationMethod: string | null - scheduledStartAt: Date | null - scheduledEndAt: Date | null - requestedAt: Date | null - confirmedAt: Date | null - completedAt: Date | null - forecastedAt: Date | null - evaluationScore: number | null - evaluationResult: "APPROVED" | "SUPPLEMENT" | "REJECTED" | null - investigationNotes: string | null - } | null - // 통합 상태를 위한 새 필드 - combinedStatus: { - status: string - label: string - variant: "default" | "outline" | "secondary" | "destructive" | "success" - } -} - -type NextRouter = ReturnType; - -interface GetColumnsProps { - setRowAction: React.Dispatch | null>>; - router: NextRouter; -} - -// 상태에 따른 Badge 변형 결정 함수 -function getStatusBadge(status: string) { - switch (status) { - case "REQUESTED": - return 요청됨 - case "IN_PROGRESS": - return 진행 중 - case "SUBMITTED": - return 제출됨 - case "APPROVED": - return 승인됨 - case "REJECTED": - return 거부됨 - default: - return {status} - } -} - -/** - * tanstack table 컬럼 정의 - */ -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" - /> - ), - size: 40, - enableSorting: false, - enableHiding: false, - } - - // ---------------------------------------------------------------- - // 2) 일반 컬럼들 - // -------------------------- - // -------------------------------------- - - const pqNoColumn: ColumnDef = { - accessorKey: "pqNumber", - header: ({ column }) => ( - - ), - cell: ({ row }) => ( -
- {row.getValue("pqNumber")} -
- ), - } - - // 협력업체 컬럼 - const vendorColumn: ColumnDef = { - accessorKey: "vendorName", - header: ({ column }) => ( - - ), - cell: ({ row }) => ( -
- {row.getValue("vendorName")} - {row.original.vendorCode ? row.original.vendorCode : "-"}/{row.original.taxId} -
- ), - } - - // PQ 유형 컬럼 - const typeColumn: ColumnDef = { - accessorKey: "type", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - return ( -
- - {row.original.pqTypeLabel} - -
- ) - }, - filterFn: (row, id, value) => { - return value.includes(row.getValue(id)) - }, - } - - // 프로젝트 컬럼 - const projectColumn: ColumnDef = { - accessorKey: "projectName", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const projectName = row.original.projectName - const projectCode = row.original.projectCode - - if (!projectName) { - return - - } - - return ( -
- {projectName} - {projectCode && ( - {projectCode} - )} -
- ) - }, - } - - // 상태 컬럼 - const statusColumn: ColumnDef = { - accessorKey: "combinedStatus", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const combinedStatus = getCombinedStatus(row.original); - return {combinedStatus.label}; - }, - filterFn: (row, id, value) => { - const combinedStatus = getCombinedStatus(row.original); - return value.includes(combinedStatus.status); - }, - }; - - // PQ 상태와 실사 상태를 결합하는 헬퍼 함수 - function getCombinedStatus(submission: PQSubmission) { - // PQ가 승인되지 않은 경우, PQ 상태를 우선 표시 - if (submission.status !== "APPROVED") { - switch (submission.status) { - case "REQUESTED": - return { status: "PQ_REQUESTED", label: "PQ 요청됨", variant: "outline" as const }; - case "IN_PROGRESS": - return { status: "PQ_IN_PROGRESS", label: "PQ 진행 중", variant: "secondary" as const }; - case "SUBMITTED": - return { status: "PQ_SUBMITTED", label: "PQ 제출됨", variant: "default" as const }; - case "REJECTED": - return { status: "PQ_REJECTED", label: "PQ 거부됨", variant: "destructive" as const }; - default: - return { status: submission.status, label: submission.status, variant: "outline" as const }; - } - } - - // PQ가 승인되었지만 실사가 없는 경우 - if (!submission.investigation) { - return { status: "PQ_APPROVED", label: "PQ 승인됨", variant: "success" as const }; - } - - // PQ가 승인되고 실사가 있는 경우 - switch (submission.investigation.investigationStatus) { - case "PLANNED": - return { status: "INVESTIGATION_PLANNED", label: "실사 계획됨", variant: "outline" as const }; - case "IN_PROGRESS": - return { status: "INVESTIGATION_IN_PROGRESS", label: "실사 진행 중", variant: "secondary" as const }; - case "COMPLETED": - // 실사 완료 후 평가 결과에 따라 다른 상태 표시 - if (submission.investigation.evaluationResult) { - switch (submission.investigation.evaluationResult) { - case "APPROVED": - return { status: "INVESTIGATION_APPROVED", label: "실사 승인", variant: "success" as const }; - case "SUPPLEMENT": - return { status: "INVESTIGATION_SUPPLEMENT", label: "실사 보완필요", variant: "secondary" as const }; - case "REJECTED": - return { status: "INVESTIGATION_REJECTED", label: "실사 불가", variant: "destructive" as const }; - default: - return { status: "INVESTIGATION_COMPLETED", label: "실사 완료", variant: "default" as const }; - } - } - return { status: "INVESTIGATION_COMPLETED", label: "실사 완료", variant: "default" as const }; - case "CANCELED": - return { status: "INVESTIGATION_CANCELED", label: "실사 취소됨", variant: "destructive" as const }; - default: - return { - status: `INVESTIGATION_${submission.investigation.investigationStatus}`, - label: `실사 ${submission.investigation.investigationStatus}`, - variant: "outline" as const - }; - } - } - - const evaluationTypeColumn: ColumnDef = { - accessorKey: "evaluationType", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const investigation = row.original.investigation; - - if (!investigation || !investigation.evaluationType) { - return -; - } - - switch (investigation.evaluationType) { - case "SITE_AUDIT": - return 실사의뢰평가; - case "QM_SELF_AUDIT": - return QM자체평가; - default: - return {investigation.evaluationType}; - } - }, - filterFn: (row, id, value) => { - const investigation = row.original.investigation; - if (!investigation || !investigation.evaluationType) return value.includes("null"); - return value.includes(investigation.evaluationType); - }, - }; - - - const evaluationResultColumn: ColumnDef = { - accessorKey: "evaluationResult", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const investigation = row.original.investigation; - - if (!investigation || !investigation.evaluationResult) { - return -; - } - - switch (investigation.evaluationResult) { - case "APPROVED": - return 승인; - case "SUPPLEMENT": - return 보완; - case "REJECTED": - return 불가; - default: - return {investigation.evaluationResult}; - } - }, - filterFn: (row, id, value) => { - const investigation = row.original.investigation; - if (!investigation || !investigation.evaluationResult) return value.includes("null"); - return value.includes(investigation.evaluationResult); - }, - }; - - // 답변 수 컬럼 - const answerCountColumn: ColumnDef = { - accessorKey: "answerCount", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - return ( -
- {row.original.answerCount} -
- ) - }, - } - - const investigationAddressColumn: ColumnDef = { - accessorKey: "investigationAddress", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const investigation = row.original.investigation; - - if (!investigation || !investigation.evaluationType) { - return -; - } - - return ( -
- {investigation.investigationAddress} -
- ) - }, - } - - const investigationNotesColumn: ColumnDef = { - accessorKey: "investigationNotes", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const investigation = row.original.investigation; - - if (!investigation || !investigation.investigationNotes) { - return -; - } - - return ( -
- {investigation.investigationNotes} -
- ) - }, - } - - - const investigationRequestedAtColumn: ColumnDef = { - accessorKey: "investigationRequestedAt", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const investigation = row.original.investigation; - - if (!investigation || !investigation.requestedAt) { - return -; - } - const dateVal = investigation.requestedAt - - return ( -
- {dateVal ? formatDate(dateVal, 'KR') : "-"} -
- ) - }, - } - - - const investigationForecastedAtColumn: ColumnDef = { - accessorKey: "investigationForecastedAt", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const investigation = row.original.investigation; - - if (!investigation || !investigation.forecastedAt) { - return -; - } - const dateVal = investigation.forecastedAt - - return ( -
- {dateVal ? formatDate(dateVal, 'KR') : "-"} -
- ) - }, - } - - const investigationConfirmedAtColumn: ColumnDef = { - accessorKey: "investigationConfirmedAt", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const investigation = row.original.investigation; - - if (!investigation || !investigation.confirmedAt) { - return -; - } - const dateVal = investigation.confirmedAt - - return ( -
- {dateVal ? formatDate(dateVal, 'KR') : "-"} -
- ) - }, - } - - const investigationCompletedAtColumn: ColumnDef = { - accessorKey: "investigationCompletedAt", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const investigation = row.original.investigation; - - if (!investigation || !investigation.completedAt) { - return -; - } - const dateVal = investigation.completedAt - - return ( -
- {dateVal ? formatDate(dateVal, 'KR') : "-"} -
- ) - }, - } - - // 제출일 컬럼 - const createdAtColumn: ColumnDef = { - accessorKey: "createdAt", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const dateVal = row.original.createdAt as Date - return formatDate(dateVal, 'KR') - }, - } - - // 제출일 컬럼 - const submittedAtColumn: ColumnDef = { - accessorKey: "submittedAt", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const dateVal = row.original.submittedAt as Date - return dateVal ? formatDate(dateVal, 'KR') : "-" - }, - } - - // 승인/거부일 컬럼 - const approvalDateColumn: ColumnDef = { - accessorKey: "approvedAt", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - if (row.original.approvedAt) { - return {formatDate(row.original.approvedAt, "KR")} - } - if (row.original.rejectedAt) { - return {formatDate(row.original.rejectedAt, "KR")} - } - return "-" - }, - } - - // ---------------------------------------------------------------- - // 3) actions 컬럼 (Dropdown 메뉴) - // ---------------------------------------------------------------- - const actionsColumn: ColumnDef = { - id: "actions", - enableHiding: false, - cell: function Cell({ row }) { - const pq = row.original - const isSubmitted = pq.status === "SUBMITTED" - const reviewUrl = `/evcp/pq_new/${pq.vendorId}/${pq.id}` - - return ( - - - - - - { - router.push(reviewUrl); - }} - > - {isSubmitted ? ( - <> - - 검토 - - ) : ( - <> - - 보기 - - )} - - - - ) - }, - size: 40, - } - - // 요청자 컬럼 추가 -const requesterColumn: ColumnDef = { - accessorKey: "requesterName", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - // PQ 요청자와 실사 요청자를 모두 표시 - const pqRequesterName = row.original.requesterName; - const investigationRequesterName = row.original.investigation?.requesterName; - - // 상태에 따라 적절한 요청자 표시 - const status = getCombinedStatus(row.original).status; - - if (status.startsWith('INVESTIGATION_') && investigationRequesterName) { - return {investigationRequesterName}; - } - - return pqRequesterName - ? {pqRequesterName} - : -; - }, -}; -const qmManagerColumn: ColumnDef = { - accessorKey: "qmManager", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const investigation = row.original.investigation; - - if (!investigation || !investigation.qmManagerName) { - return -; - } - - return ( -
- {investigation.qmManagerName} - {investigation.qmManagerEmail && ( - {investigation.qmManagerEmail} - )} -
- ); - }, -}; - - - // ---------------------------------------------------------------- - // 4) 최종 컬럼 배열 - // ---------------------------------------------------------------- - return [ - selectColumn, - statusColumn, // 통합된 진행현황 컬럼 - pqNoColumn, - vendorColumn, - investigationAddressColumn, - typeColumn, - projectColumn, - createdAtColumn, - submittedAtColumn, - approvalDateColumn, - answerCountColumn, - evaluationTypeColumn, // 평가 유형 컬럼 - investigationForecastedAtColumn, - investigationRequestedAtColumn, - investigationConfirmedAtColumn, - investigationCompletedAtColumn, - evaluationResultColumn, // 평가 결과 컬럼 - requesterColumn, - qmManagerColumn, - investigationNotesColumn, - actionsColumn, - ]; +"use client" + +import * as React from "react" +import { type DataTableRowAction } from "@/types/table" +import { type ColumnDef } from "@tanstack/react-table" +import { Ellipsis, Eye, FileEdit, Trash2, Building2, FileText, Edit } from "lucide-react" + +import { formatDate } from "@/lib/utils" +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" +import { Checkbox } from "@/components/ui/checkbox" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"; +import { useRouter } from "next/navigation" +import { PQDeleteDialog } from "@/components/pq-input/pq-delete-dialog" + +// PQ 제출 타입 정의 +export interface PQSubmission { + // PQ 제출 정보 + id: number + pqNumber: string + type: string + status: string + requesterName: string | null // 요청자 이름 + createdAt: Date + updatedAt: Date + submittedAt: Date | null + approvedAt: Date | null + rejectedAt: Date | null + rejectReason: string | null + + // 협력업체 정보 + vendorId: number + vendorName: string + vendorCode: string + taxId: string + vendorStatus: string + email: string + // 프로젝트 정보 + projectId: number | null + projectName: string | null + projectCode: string | null + + // 답변 정보 + answerCount: number + attachmentCount: number + + // PQ 상태 + pqStatus: string + pqTypeLabel: string + + // PQ 대상품목 + pqItems: string | null + + // 방문실사 요청 정보 + siteVisitRequestId: number | null // 방문실사 요청 ID + + // 실사 정보 + investigation: { + id: number + investigationStatus: string + requesterName: string | null // 실사 요청자 이름 + evaluationType: "PURCHASE_SELF_EVAL" | "DOCUMENT_EVAL" | "PRODUCT_INSPECTION" | "SITE_VISIT_EVAL" | null + qmManagerId: number | null + qmManagerName: string | null // QM 담당자 이름 + qmManagerEmail: string | null // QM 담당자 이메일 + investigationAddress: string | null + investigationMethod: string | null + scheduledStartAt: Date | null + scheduledEndAt: Date | null + requestedAt: Date | null + confirmedAt: Date | null + completedAt: Date | null + forecastedAt: Date | null + evaluationScore: number | null + evaluationResult: "APPROVED" | "SUPPLEMENT" | "REJECTED" | "RESULT_SENT" | null + investigationNotes: string | null + } | null + // 통합 상태를 위한 새 필드 + combinedStatus: { + status: string + label: string + variant: "default" | "outline" | "secondary" | "destructive" | "success" + } +} + +type NextRouter = ReturnType; + +interface GetColumnsProps { + setRowAction: React.Dispatch | null>>; + router: NextRouter; +} + +// 상태에 따른 Badge 변형 결정 함수 +function getStatusBadge(status: string) { + switch (status) { + case "REQUESTED": + return 요청됨 + case "IN_PROGRESS": + return 진행 중 + case "SUBMITTED": + return 제출됨 + case "APPROVED": + return 승인됨 + case "REJECTED": + return 거부됨 + default: + return {status} + } +} + +/** + * tanstack table 컬럼 정의 + */ +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" + /> + ), + size: 40, + enableSorting: false, + enableHiding: false, + } + + // ---------------------------------------------------------------- + // 2) 일반 컬럼들 + // -------------------------- + // -------------------------------------- + + const pqNoColumn: ColumnDef = { + accessorKey: "pqNumber", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ {row.getValue("pqNumber")} +
+ ), + } + + // 협력업체 컬럼 + const vendorColumn: ColumnDef = { + accessorKey: "vendorName", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ {row.getValue("vendorName")} + {row.original.vendorCode ? row.original.vendorCode : "-"}/{row.original.taxId} +
+ ), + } + + // PQ 유형 컬럼 + const typeColumn: ColumnDef = { + accessorKey: "type", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const { type, pqTypeLabel } = row.original; + let label = pqTypeLabel; + if (type === "NON_INSPECTION") { + label = "미실사 PQ"; + } + return ( +
+ + {label} + +
+ ); + }, + filterFn: (row, id, value) => { + return value.includes(row.getValue(id)); + }, + } + + // 프로젝트 컬럼 + const projectColumn: ColumnDef = { + accessorKey: "projectName", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const projectName = row.original.projectName + const projectCode = row.original.projectCode + + if (!projectName) { + return - + } + + return ( +
+ {projectName} + {projectCode && ( + {projectCode} + )} +
+ ) + }, + } + + // 상태 컬럼 + const statusColumn: ColumnDef = { + accessorKey: "combinedStatus", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const combinedStatus = getCombinedStatus(row.original); + return {combinedStatus.label}; + }, + filterFn: (row, id, value) => { + const combinedStatus = getCombinedStatus(row.original); + return value.includes(combinedStatus.status); + }, + }; + + // PQ 상태와 실사 상태를 결합하는 헬퍼 함수 + function getCombinedStatus(submission: PQSubmission) { + // PQ가 승인되지 않은 경우, PQ 상태를 우선 표시 + if (submission.status !== "APPROVED") { + switch (submission.status) { + case "REQUESTED": + return { status: "PQ_REQUESTED", label: "PQ 요청됨", variant: "outline" as const }; + case "IN_PROGRESS": + return { status: "PQ_IN_PROGRESS", label: "PQ 진행 중", variant: "secondary" as const }; + case "SUBMITTED": + return { status: "PQ_SUBMITTED", label: "PQ 제출됨", variant: "default" as const }; + case "REJECTED": + return { status: "PQ_REJECTED", label: "PQ 거부됨", variant: "destructive" as const }; + default: + return { status: submission.status, label: submission.status, variant: "outline" as const }; + } + } + + // PQ가 승인되었지만 실사가 없는 경우 + if (!submission.investigation) { + return { status: "PQ_APPROVED", label: "PQ 승인됨", variant: "success" as const }; + } + + // PQ가 승인되고 실사가 있는 경우 + switch (submission.investigation.investigationStatus) { + case "PLANNED": + return { status: "INVESTIGATION_PLANNED", label: "실사 계획됨", variant: "outline" as const }; + case "IN_PROGRESS": + return { status: "INVESTIGATION_IN_PROGRESS", label: "실사 진행 중", variant: "secondary" as const }; + case "COMPLETED": + // 실사 완료 후 평가 결과에 따라 다른 상태 표시 + if (submission.investigation.evaluationResult) { + switch (submission.investigation.evaluationResult) { + case "APPROVED": + return { status: "INVESTIGATION_APPROVED", label: "실사 승인", variant: "success" as const }; + case "SUPPLEMENT": + return { status: "INVESTIGATION_SUPPLEMENT", label: "실사 보완필요", variant: "secondary" as const }; + case "REJECTED": + return { status: "INVESTIGATION_REJECTED", label: "실사 불가", variant: "destructive" as const }; + default: + return { status: "INVESTIGATION_COMPLETED", label: "실사 완료", variant: "default" as const }; + } + } + return { status: "INVESTIGATION_COMPLETED", label: "실사 완료", variant: "default" as const }; + case "CANCELED": + return { status: "INVESTIGATION_CANCELED", label: "실사 취소됨", variant: "destructive" as const }; + case "RESULT_SENT": + return { status: "INVESTIGATION_RESULT_SENT", label: "실사 결과 발송", variant: "success" as const }; + default: + return { + status: `INVESTIGATION_${submission.investigation.investigationStatus}`, + label: `실사 ${submission.investigation.investigationStatus}`, + variant: "outline" as const + }; + } + } + + const evaluationTypeColumn: ColumnDef = { + accessorKey: "evaluationType", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const investigation = row.original.investigation; + + if (!investigation || !investigation.evaluationType) { + return -; + } + + switch (investigation.evaluationType) { + case "PURCHASE_SELF_EVAL": + return 구매자체평가; + case "DOCUMENT_EVAL": + return 서류평가; + case "PRODUCT_INSPECTION": + return 제품검사평가; + case "SITE_VISIT_EVAL": + return 방문실사평가; + default: + return {investigation.evaluationType}; + } + }, + filterFn: (row, id, value) => { + const investigation = row.original.investigation; + if (!investigation || !investigation.evaluationType) return value.includes("null"); + return value.includes(investigation.evaluationType); + }, + }; + + + const evaluationResultColumn: ColumnDef = { + accessorKey: "evaluationResult", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const investigation = row.original.investigation; + + if (!investigation || !investigation.evaluationResult) { + return -; + } + + switch (investigation.evaluationResult) { + case "APPROVED": + return 승인; + case "SUPPLEMENT": + return 보완; + case "REJECTED": + return 불가; + default: + return {investigation.evaluationResult}; + } + }, + filterFn: (row, id, value) => { + const investigation = row.original.investigation; + if (!investigation || !investigation.evaluationResult) return value.includes("null"); + return value.includes(investigation.evaluationResult); + }, + }; + + // 답변 수 컬럼 + const answerCountColumn: ColumnDef = { + accessorKey: "answerCount", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + return ( +
+ {row.original.answerCount} +
+ ) + }, + } + + const investigationAddressColumn: ColumnDef = { + accessorKey: "investigationAddress", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const investigation = row.original.investigation; + + if (!investigation || !investigation.evaluationType) { + return -; + } + + return ( +
+ {investigation.investigationAddress} +
+ ) + }, + } + + const investigationNotesColumn: ColumnDef = { + accessorKey: "investigationNotes", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const investigation = row.original.investigation; + + if (!investigation || !investigation.investigationNotes) { + return -; + } + + return ( +
+ {investigation.investigationNotes} +
+ ) + }, + } + const investigationMethodColumn: ColumnDef = { + accessorKey: "investigationMethod", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const investigation = row.original.investigation; + if (!investigation || !investigation.investigationMethod) { + return -; + } + + switch (investigation.investigationMethod) { + case "PURCHASE_SELF_EVAL": + return 구매자체평가; + case "DOCUMENT_EVAL": + return 서류평가; + case "PRODUCT_INSPECTION": + return 제품검사평가; + case "SITE_VISIT_EVAL": + return 방문실사평가; + default: + return {investigation.investigationMethod}; + } + }, + } + + // 실사품목 컬럼 + const pqItemsColumn: ColumnDef = { + accessorKey: "pqItems", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const pqItems = row.original.pqItems; + + if (!pqItems) { + return -; + } + + return ( +
+ {pqItems} +
+ ) + }, + } + + + const investigationRequestedAtColumn: ColumnDef = { + accessorKey: "investigationRequestedAt", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const investigation = row.original.investigation; + + if (!investigation || !investigation.requestedAt) { + return -; + } + const dateVal = investigation.requestedAt + + return ( +
+ {dateVal ? formatDate(dateVal, 'KR') : "-"} +
+ ) + }, + } + + + const investigationForecastedAtColumn: ColumnDef = { + accessorKey: "investigationForecastedAt", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const investigation = row.original.investigation; + + if (!investigation || !investigation.forecastedAt) { + return -; + } + const dateVal = investigation.forecastedAt + + return ( +
+ {dateVal ? formatDate(dateVal, 'KR') : "-"} +
+ ) + }, + } + + const investigationConfirmedAtColumn: ColumnDef = { + accessorKey: "investigationConfirmedAt", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const investigation = row.original.investigation; + + if (!investigation || !investigation.confirmedAt) { + return -; + } + const dateVal = investigation.confirmedAt + + return ( +
+ {dateVal ? formatDate(dateVal, 'KR') : "-"} +
+ ) + }, + } + + const investigationCompletedAtColumn: ColumnDef = { + accessorKey: "investigationCompletedAt", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const investigation = row.original.investigation; + + if (!investigation || !investigation.completedAt) { + return -; + } + const dateVal = investigation.completedAt + + return ( +
+ {dateVal ? formatDate(dateVal, 'KR') : "-"} +
+ ) + }, + } + + // 제출일 컬럼 + const createdAtColumn: ColumnDef = { + accessorKey: "createdAt", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const dateVal = row.original.createdAt as Date + return formatDate(dateVal, 'KR') + }, + } + + // 제출일 컬럼 + const submittedAtColumn: ColumnDef = { + accessorKey: "submittedAt", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const dateVal = row.original.submittedAt as Date + return dateVal ? formatDate(dateVal, 'KR') : "-" + }, + } + + // 승인/거부일 컬럼 + const approvalDateColumn: ColumnDef = { + accessorKey: "approvedAt", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + if (row.original.approvedAt) { + return {formatDate(row.original.approvedAt)} + } + if (row.original.rejectedAt) { + return {formatDate(row.original.rejectedAt)} + } + return "-" + }, + } + + // ---------------------------------------------------------------- + // 3) actions 컬럼 (Dropdown 메뉴) + // ---------------------------------------------------------------- + const actionsColumn: ColumnDef = { + id: "actions", + enableHiding: false, + cell: function Cell({ row }) { + const pq = row.original + const isSubmitted = pq.status === "SUBMITTED" + const reviewUrl = `/evcp/pq_new/${pq.vendorId}/${pq.id}` + + return ( + + + + + + { + router.push(reviewUrl); + }} + > + {isSubmitted ? ( + <> + + 검토 + + ) : ( + <> + + 보기 + + )} + + + {/* 방문실사 버튼 - 제품검사평가 또는 방문실사평가인 경우에만 표시 */} + {pq.investigation && + (pq.investigation.investigationMethod === "PRODUCT_INSPECTION" || + pq.investigation.investigationMethod === "SITE_VISIT_EVAL") && ( + <> + { + e.preventDefault(); + // 방문실사 다이얼로그 열기 로직 + setRowAction({ + type: "site-visit", + row: row.original + }); + }} + > + + 방문실사 + + { + e.preventDefault(); + // 협력업체 정보 조회 다이얼로그 열기 로직 + setRowAction({ + type: "vendor-info-view", + row: row.original + }); + }} + > + + 협력업체 정보 조회 + + + )} + + {/* 실사 정보 수정 버튼 - 구매자체평가인 경우에만 표시 */} + {pq.investigation && + pq.investigation.investigationMethod === "PURCHASE_SELF_EVAL" && ( + { + e.preventDefault(); + // 실사 정보 수정 다이얼로그 열기 로직 + setRowAction({ + type: "edit-investigation", + row: row.original + }); + }} + > + + 실사 정보 수정 + + )} + + {/* 삭제 메뉴 - REQUESTED 상태일 때만 표시 */} + {pq.status === "REQUESTED" && ( + + { + e.preventDefault(); + }} + className="text-destructive focus:text-destructive" + > + + 삭제 + + + )} + + + ) + }, + size: 40, + } + + // 요청자 컬럼 추가 +const requesterColumn: ColumnDef = { + accessorKey: "requesterName", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + // PQ 요청자와 실사 요청자를 모두 표시 + const pqRequesterName = row.original.requesterName; + const investigationRequesterName = row.original.investigation?.requesterName; + + // 상태에 따라 적절한 요청자 표시 + const status = getCombinedStatus(row.original).status; + + if (status.startsWith('INVESTIGATION_') && investigationRequesterName) { + return {investigationRequesterName}; + } + + return pqRequesterName + ? {pqRequesterName} + : -; + }, +}; +const qmManagerColumn: ColumnDef = { + accessorKey: "qmManager", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const investigation = row.original.investigation; + + if (!investigation || !investigation.qmManagerName) { + return -; + } + + return ( +
+ {investigation.qmManagerName} + {investigation.qmManagerEmail && ( + {investigation.qmManagerEmail} + )} +
+ ); + }, +}; + + + // ---------------------------------------------------------------- + // 4) 최종 컬럼 배열 + // ---------------------------------------------------------------- + return [ + selectColumn, + statusColumn, // 통합된 진행현황 컬럼 + pqNoColumn, + vendorColumn, + investigationAddressColumn, + typeColumn, + projectColumn, + pqItemsColumn, // 실사품목 컬럼 + createdAtColumn, + submittedAtColumn, + approvalDateColumn, + answerCountColumn, + evaluationTypeColumn, // 평가 유형 컬럼 + investigationMethodColumn, + investigationForecastedAtColumn, + investigationRequestedAtColumn, + investigationConfirmedAtColumn, + investigationCompletedAtColumn, + evaluationResultColumn, // 평가 결과 컬럼 + requesterColumn, + qmManagerColumn, + investigationNotesColumn, + actionsColumn, + ]; } \ No newline at end of file -- cgit v1.2.3