"use client" import * as React from "react" import { type DataTableRowAction } from "@/types/table" import { type ColumnDef } from "@tanstack/react-table" import { Ellipsis, Edit, Trash2, Plus, Copy } from "lucide-react" import { cn, compareItemNumber, 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, DropdownMenuShortcut, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip" import { toast } from "sonner" import { useSession } from "next-auth/react" import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" import { type GtcClauseTreeView } from "@/db/schema/gtc" interface GetColumnsProps { setRowAction: React.Dispatch | null>> documentId: number hasVendorInfo?: boolean } export function getColumns({ setRowAction, documentId, hasVendorInfo }: GetColumnsProps): ColumnDef[] { // 1) select const selectColumn: ColumnDef = { id: "select", header: ({ table }) => ( table.toggleAllPageRowsSelected(!!v)} aria-label="Select all" className="translate-y-0.5" /> ), cell: ({ row }) => ( row.toggleSelected(!!v)} aria-label="Select row" className="translate-y-0.5" /> ), size: 40, enableSorting: false, enableHiding: false, } // 2) 조항 정보 const clauseInfoColumns: ColumnDef[] = [ { accessorKey: "itemNumber", header: ({ column }) => , cell: ({ row }) => { const itemNumber = row.getValue("itemNumber") as string const depth = row.original.depth const childrenCount = row.original.childrenCount const isModified = row.original.vendorInfo?.isNumberModified return (
{itemNumber} {childrenCount > 0 && ( {childrenCount}

{childrenCount}개의 하위 조항

)}
) }, size: 100, enableResizing: true, sortingFn: (rowA, rowB, colId) => compareItemNumber(rowA.getValue(colId), rowB.getValue(colId)), meta: { excelHeader: "채번" }, }, { accessorKey: "category", header: ({ column }) => , cell: ({ row }) => { const category = row.getValue("category") as string const isModified = row.original.vendorInfo?.isCategoryModified return category ? ( {category} ) : ( - ) }, size: 100, enableResizing: true, meta: { excelHeader: "분류" }, }, { accessorKey: "subtitle", header: ({ column }) => , cell: ({ row }) => { const subtitle = row.getValue("subtitle") as string const depth = row.original.depth const isModified = row.original.vendorInfo?.isSubtitleModified return (
= 2 && "text-sm text-muted-foreground", isModified && "text-red-500 dark:text-red-400" )} title={subtitle} > {subtitle}
) }, size: 150, enableResizing: true, meta: { excelHeader: "소제목" }, }, { accessorKey: "content", header: ({ column }) => , cell: ({ row }) => { const modifiedContent = row.original.vendorInfo?.modifiedContent const content = modifiedContent ? modifiedContent : row.getValue("content") as string | null if (!content) { return (
그룹핑 조항 상세내용 없음
) } const truncated = content.length > 100 ? `${content.substring(0, 100)}...` : content return (
{/*

{content}

*/}

{content}

{content}

) }, size: 200, maxSize: 500, enableResizing: true, meta: { excelHeader: "상세항목" }, }, ] // 3) 등록/수정 정보 const auditColumns: ColumnDef[] = [ { accessorKey: "createdAt", header: ({ column }) => , cell: ({ row }) => { const date = row.getValue("createdAt") as Date return date ? formatDate(date, "KR") : "-" }, size: 120, enableResizing: true, meta: { excelHeader: "작성일" }, }, { accessorKey: "createdByName", header: ({ column }) => , cell: ({ row }) => { const v = row.getValue("createdByName") as string return v ? {v} : - }, size: 80, enableResizing: true, meta: { excelHeader: "작성자" }, }, { accessorKey: "updatedAt", header: ({ column }) => , cell: ({ row }) => { const date = row.getValue("updatedAt") as Date return {date ? formatDate(date, "KR") : "-"} }, size: 120, enableResizing: true, meta: { excelHeader: "수정일" }, }, { accessorKey: "updatedByName", header: ({ column }) => , cell: ({ row }) => { const v = row.getValue("updatedByName") as string return v ? {v} : - }, size: 80, enableResizing: true, meta: { excelHeader: "수정자" }, }, ] // 벤더 관련 칼럼 추가 const vendorColumns: ColumnDef[] = hasVendorInfo ? [ { id: "vendorReviewStatus", accessorFn: (row) => row.vendorInfo?.reviewStatus, header: ({ column }) => , cell: ({ row }) => { const status = row.original.vendorInfo?.reviewStatus if (!status) return - const statusMap = { draft: { label: "초안", variant: "secondary" }, pending: { label: "대기", variant: "outline" }, reviewing: { label: "협의중", variant: "default" }, approved: { label: "승인", variant: "success" }, rejected: { label: "거부", variant: "destructive" }, revised: { label: "수정", variant: "warning" }, } const config = statusMap[status as keyof typeof statusMap] return {config.label} }, size: 80, }, { id: "vendorComment", accessorFn: (row) => row.vendorInfo?.latestComment, header: ({ column }) => , cell: ({ row }) => { const comment = row.original.vendorInfo?.latestComment const history = row.original.vendorInfo?.negotiationHistory if (!comment) return - return (
{comment} {history && history.length > 1 && ( {history.length} )}
{history?.slice(0, 3).map((h: any, idx: number) => (

{h.actorName} • {formatDate(h.createdAt, "KR")}

{h.comment}

))}
) }, size: 200, }, { id: "vendorModifications", header: ({ column }) => , cell: ({ row }) => { const info = row.original.vendorInfo if (!info) return - const mods = [] if (info.isNumberModified) mods.push("채번") if (info.isCategoryModified) mods.push("분류") if (info.isSubtitleModified) mods.push("소제목") if (info.isContentModified) mods.push("내용") if (mods.length === 0) return 없음 return (
{mods.map((mod) => ( {mod} ))}
) }, size: 150, }, ] : [] // 4) actions const actionsColumn: ColumnDef = { id: "actions", enableHiding: false, cell: function Cell({ row }) { const { data: session } = useSession() const gtcClause = row.original const currentUserId = React.useMemo( () => (session?.user?.id ? Number(session.user.id) : null), [session], ) const handleEdit = () => setRowAction({ row, type: "update" }) const handleDelete = () => setRowAction({ row, type: "delete" }) const handleAddSubClause = () => setRowAction({ row, type: "addSubClause" }) const handleDuplicate = () => setRowAction({ row, type: "duplicate" }) return ( 협의 확인 및 조항 수정 {/* 하위 조항 추가 복제 삭제 ⌘⌫ */} ) }, size: 40, maxSize: 40, } // 🔹 그룹 헤더 제거: 평탄화된 컬럼 배열 반환 return [ selectColumn, ...clauseInfoColumns, ...vendorColumns, // 벤더 칼럼 추가 ...auditColumns, actionsColumn, ] }