// initial-rfq-detail-columns.tsx "use client" import * as React from "react" import { type ColumnDef } from "@tanstack/react-table" import { type Row } from "@tanstack/react-table" import { Ellipsis, Building, Eye, Edit, Trash, MessageSquare, Settings, CheckCircle2, XCircle } 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, DropdownMenuSeparator, DropdownMenuTrigger, DropdownMenuShortcut } from "@/components/ui/dropdown-menu" import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" import { InitialRfqDetailView } from "@/db/schema" // RowAction 타입 정의 export interface DataTableRowAction { row: Row type: "update" | "delete" } interface GetInitialRfqDetailColumnsProps { onSelectDetail?: (detail: any) => void setRowAction?: React.Dispatch | null>> } export function getInitialRfqDetailColumns({ onSelectDetail, setRowAction }: GetInitialRfqDetailColumnsProps = {}): ColumnDef[] { return [ /** ───────────── 체크박스 ───────────── */ { 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, }, /** ───────────── RFQ 정보 ───────────── */ { accessorKey: "initialRfqStatus", header: ({ column }) => ( ), cell: ({ row }) => { const status = row.getValue("initialRfqStatus") as string const getInitialStatusColor = (status: string) => { switch (status) { case "DRAFT": return "outline" case "Init. RFQ Sent": return "default" case "Init. RFQ Answered": return "success" case "S/L Decline": return "destructive" default: return "secondary" } } return ( {status} ) }, size: 120 }, { accessorKey: "rfqCode", header: ({ column }) => ( ), cell: ({ row }) => (
{row.getValue("rfqCode") as string}
), size: 120, }, { accessorKey: "rfqRevision", header: ({ column }) => ( ), cell: ({ row }) => (
Rev. {row.getValue("rfqRevision") as number}
), size: 120, }, /** ───────────── 벤더 정보 ───────────── */ { id: "vendorInfo", header: ({ column }) => ( ), cell: ({ row }) => { const vendorName = row.original.vendorName as string const vendorCode = row.original.vendorCode as string const vendorType = row.original.vendorCategory as string const vendorCountry = row.original.vendorCountry === "KR" ? "D":"F" const businessSize = row.original.vendorBusinessSize as string return (
{vendorName}
{vendorCode} • {vendorType} • {vendorCountry}
{businessSize && ( {businessSize} )}
) }, size: 200, }, { accessorKey: "cpRequestYn", header: ({ column }) => ( ), cell: ({ row }) => { const cpRequest = row.getValue("cpRequestYn") as boolean return cpRequest ? ( Yes ) : ( - ) }, size: 60, }, { accessorKey: "prjectGtcYn", header: ({ column }) => ( ), cell: ({ row }) => { const projectGtc = row.getValue("prjectGtcYn") as boolean return projectGtc ? ( Yes ) : ( - ) }, size: 100, }, { accessorKey: "gtcYn", header: ({ column }) => ( ), cell: ({ row }) => { const gtc = row.getValue("gtcYn") as boolean return gtc ? ( Yes ) : ( - ) }, size: 60, }, { accessorKey: "gtcValidDate", header: ({ column }) => ( ), cell: ({ row }) => { const gtcValidDate = row.getValue("gtcValidDate") as string return gtcValidDate ? (
{gtcValidDate}
) : ( - ) }, size: 100, }, { accessorKey: "classification", header: ({ column }) => ( ), cell: ({ row }) => { const classification = row.getValue("classification") as string return classification ? (
{classification}
) : ( - ) }, size: 120, }, { accessorKey: "sparepart", header: ({ column }) => ( ), cell: ({ row }) => { const sparepart = row.getValue("sparepart") as string return sparepart ? ( {sparepart} ) : ( - ) }, size: 100, }, { id: "incoterms", header: ({ column }) => ( ), cell: ({ row }) => { const code = row.original.incotermsCode as string const description = row.original.incotermsDescription as string return code ? (
{code} {description && (
{description}
)}
) : ( - ) }, size: 120, }, /** ───────────── 날짜 정보 ───────────── */ { accessorKey: "validDate", header: ({ column }) => ( ), cell: ({ row }) => { const validDate = row.getValue("validDate") as Date return validDate ? (
{formatDate(validDate)}
) : ( - ) }, size: 100, }, { accessorKey: "dueDate", header: ({ column }) => ( ), cell: ({ row }) => { const dueDate = row.getValue("dueDate") as Date const isOverdue = dueDate && new Date(dueDate) < new Date() return dueDate ? (
{formatDate(dueDate)}
{isOverdue && (
지연
)}
) : ( - ) }, size: 120, }, { accessorKey: "returnYn", header: ({ column }) => ( ), cell: ({ row }) => { const returnFlag = row.getValue("returnYn") as boolean return returnFlag ? ( Yes ) : ( - ) }, size: 70, }, { accessorKey: "returnRevision", header: ({ column }) => ( ), cell: ({ row }) => { const revision = row.getValue("returnRevision") as number return revision > 0 ? ( Rev. {revision} ) : ( - ) }, size: 80, }, { accessorKey: "shortList", header: ({ column }) => ( ), cell: ({ row }) => { const shortList = row.getValue("shortList") as boolean return shortList ? ( Yes ) : ( - ) }, size: 90, }, /** ───────────── 등록/수정 정보 ───────────── */ { accessorKey: "createdAt", header: ({ column }) => ( ), cell: ({ row }) => { const created = row.getValue("createdAt") as Date const updated = row.original.updatedAt as Date return (
{formatDate(created)}
{updated && new Date(updated) > new Date(created) && (
수정: {formatDate(updated, "KR")}
)}
) }, size: 120, }, /** ───────────── 액션 ───────────── */ { id: "actions", enableHiding: false, cell: function Cell({ row }) { return ( 벤더 응답 보기 {setRowAction && ( <> setRowAction({ row, type: "update" })} > 수정 setRowAction({ row, type: "delete" })} > 삭제 ⌘⌫ )} ) }, size: 40, }, ] }