"use client" import * as React from "react" import { type DataTableRowAction } from "@/types/table" import { type ColumnDef } from "@tanstack/react-table" import { FileText, Edit, Send, Eye, Clock, CheckCircle, AlertCircle, XCircle, Mail, UserX } from "lucide-react" import { formatCurrency, formatDate, formatDateTime } from "@/lib/utils" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Checkbox } from "@/components/ui/checkbox" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip" import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" import { useRouter } from "next/navigation" import { ParticipationDialog } from "./participation-dialog" import { VendorQuotationView } from "@/db/schema" // 통합 상태 배지 컴포넌트 (displayStatus 사용) function DisplayStatusBadge({ status }: { status: string | null }) { if (!status) return null const config = { "미응답": { variant: "secondary" as const, icon: Mail, label: "응답 대기" }, "불참": { variant: "destructive" as const, icon: UserX, label: "불참" }, "작성중": { variant: "outline" as const, icon: Edit, label: "작성중" }, "제출완료": { variant: "default" as const, icon: CheckCircle, label: "제출완료" }, "수정요청": { variant: "warning" as const, icon: AlertCircle, label: "수정요청" }, "최종확정": { variant: "success" as const, icon: CheckCircle, label: "최종확정" }, "취소": { variant: "destructive" as const, icon: XCircle, label: "취소" }, } const { variant, icon: Icon, label } = config[status as keyof typeof config] || { variant: "outline" as const, icon: Clock, label: status } return ( {label} ) } // RFQ 상태 배지 (기존 유지) function RfqStatusBadge({ status }: { status: string }) { const config: Record = { "RFQ 생성": { variant: "outline" }, "구매담당지정": { variant: "secondary" }, "견적요청문서 확정": { variant: "secondary" }, "TBE 완료": { variant: "warning" }, "RFQ 발송": { variant: "default" }, "견적접수": { variant: "success" }, "최종업체선정": { variant: "success" }, } const { variant } = config[status] || { variant: "outline" as const } return {status} } type NextRouter = ReturnType interface GetColumnsProps { setRowAction: React.Dispatch | null>>; router: NextRouter; vendorId: number; // 추가: 벤더 ID 전달 } export function getColumns({ setRowAction, router, vendorId, // 추가 }: GetColumnsProps): ColumnDef[] { // 체크박스 컬럼 (기존 유지) 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, } // 액션 컬럼 const actionsColumn: ColumnDef = { id: "actions", header: "작업", enableHiding: false, cell: ({ row }) => { const rfqId = row.original.id const rfqCode = row.original.rfqCode const displayStatus = row.original.displayStatus const rfqLastDetailsId = row.original.rfqLastDetailsId const [showParticipationDialog, setShowParticipationDialog] = React.useState(false) // displayStatus 기반으로 액션 결정 switch (displayStatus) { case "미응답": return ( <> {showParticipationDialog && ( setShowParticipationDialog(false)} /> )} ) case "불참": return ( 불참 {row.original.nonParticipationReason && (

불참 사유: {row.original.nonParticipationReason}

)}
) case "작성중": case "대기중": return ( ) case "수정요청": return ( ) case "제출완료": case "최종확정": return ( ) case "취소": return ( 취소됨 ) default: return null } }, size: 150, } // 기본 컬럼들 const columns: ColumnDef[] = [ selectColumn, { accessorKey: "rfqCode", header: ({ column }) => ( ), cell: ({ row }) => { const value = row.getValue("rfqCode") return ( {value || "-"} ) }, size: 140, minSize: 120, maxSize: 180, enableResizing: true, }, { accessorKey: "rfqType", header: ({ column }) => ( ), cell: ({ row }) => { const rfqCode = row.original.rfqCode const value = row.getValue("rfqType") // RFQ 코드의 앞자리에 따라 유형 결정 if (rfqCode?.startsWith('I')) { return "ITB" } else if (rfqCode?.startsWith('R')) { return "RFQ" } else if (rfqCode?.startsWith('F')) { return "일반견적" } // 기존 rfqType 값이 있는 경우 (백업) const typeMap: Record = { "ITB": "ITB", "RFQ": "RFQ", "일반견적": "일반견적" } return typeMap[value as string] || value || "-" }, size: 100, minSize: 80, maxSize: 120, enableResizing: true, enableHiding: true, }, // { // accessorKey: "rfqTitle", // header: ({ column }) => ( // // ), // cell: ({ row }) => { // const rfqCode = row.original.rfqCode // const value = row.getValue("rfqTitle") // // F로 시작하지 않으면 빈 값 반환 // if (!rfqCode?.startsWith('F')) { // return null // } // return value || "-" // }, // minSize: 200, // maxSize: 400, // enableResizing: true, // enableHiding: true, // }, { accessorKey: "projectName", header: ({ column }) => ( ), cell: ({ row }) => (
{row.original.projectCode} {row.original.projectName || "-"}
), minSize: 150, maxSize: 300, enableResizing: true, }, { accessorKey: "itemName", header: ({ column }) => ( ), cell: ({ row }) => row.getValue("itemName") || "-", minSize: 150, maxSize: 300, enableResizing: true, }, { accessorKey: "packageName", header: ({ column }) => ( ), cell: ({ row }) => (
{row.original.packageNo} {row.original.packageName || "-"}
), minSize: 120, maxSize: 250, enableResizing: true, }, { accessorKey: "MaterialGroup", header: ({ column }) => ( ), cell: ({ row }) => (
{row.original.majorItemMaterialCategory} {row.original.majorItemMaterialDescription || "-"}
), minSize: 120, maxSize: 250, enableResizing: true, }, { id: "rfqDocument", header: ({ column }) => , cell: ({ row }) => ( ), size: 80, }, // 견적품목수 - 수정됨 { accessorKey: "prItemsCount", header: ({ column }) => , cell: ({ row }) => ( ), size: 90, }, { accessorKey: "engPicName", header: ({ column }) => , cell: ({ row }) => row.original.engPicName || "-", size: 100, }, { accessorKey: "picUserName", header: ({ column }) => , cell: ({ row }) => row.original.picUserName || row.original.picName || "-", size: 100, }, { accessorKey: "submittedAt", header: ({ column }) => ( ), cell: ({ row }) => { return row.original.submittedAt ? formatDateTime(new Date(row.original.submittedAt)) : "-" }, size: 150, minSize: 120, maxSize: 180, enableResizing: true, }, { accessorKey: "totalAmount", header: ({ column }) => ( ), cell: ({ row }) => { if (!row.original.totalAmount) return "-" return formatCurrency( row.original.totalAmount, row.original.vendorCurrency || "USD" ) }, size: 140, minSize: 120, maxSize: 180, enableResizing: true, }, { accessorKey: "displayStatus", // 변경: responseStatus → displayStatus header: ({ column }) => ( ), cell: ({ row }) => , size: 120, minSize: 100, maxSize: 150, enableResizing: true, }, { accessorKey: "rfqSendDate", header: ({ column }) => ( ), cell: ({ row }) => { const value = row.getValue("rfqSendDate") return value ? formatDateTime(new Date(value as string)) : "-" }, size: 150, minSize: 120, maxSize: 180, enableResizing: true, }, { accessorKey: "participationRepliedAt", // 추가: 참여 응답일 header: ({ column }) => ( ), cell: ({ row }) => { const value = row.getValue("participationRepliedAt") return value ? formatDateTime(new Date(value as string)) : "-" }, size: 150, minSize: 120, maxSize: 180, enableResizing: true, enableHiding: true, // 선택적 표시 }, { accessorKey: "dueDate", header: ({ column }) => ( ), cell: ({ row }) => { const value = row.getValue("dueDate") const now = new Date() const dueDate = value ? new Date(value as string) : null const isOverdue = dueDate && dueDate < now const isNearDeadline = dueDate && (dueDate.getTime() - now.getTime()) < (24 * 60 * 60 * 1000) // 24시간 이내 return ( {dueDate ? formatDateTime(dueDate) : "-"} ) }, size: 150, minSize: 120, maxSize: 180, enableResizing: true, }, actionsColumn, ] return columns }