"use client" import * as React from "react" import { type DataTableRowAction } from "@/types/table" import { type ColumnDef, type Row, type Column } from "@tanstack/react-table" import { Ellipsis } from "lucide-react" import { formatDate } from "@/lib/utils" import { Button } from "@/components/ui/button" import { Checkbox } from "@/components/ui/checkbox" import { Badge } from "@/components/ui/badge" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuShortcut, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { ContactPossibleItemDetail } from "../service" import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" import { contactPossibleItemsColumnsConfig } from "@/config/contactPossibleItemsColumnsConfig" interface GetColumnsProps { setRowAction: React.Dispatch | null>>; } /** * tanstack table 컬럼 정의 (중첩 헤더 버전) */ export function getColumns({ setRowAction }: 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) actions 컬럼 (Dropdown 메뉴) // ---------------------------------------------------------------- const actionsColumn: ColumnDef = { id: "actions", enableHiding: false, cell: function Cell({ row }) { return ( setRowAction({ row, type: "delete" })} > 삭제 ⌘⌫ ) }, size: 40, } // ---------------------------------------------------------------- // 3) config를 기반으로 컬럼 그룹들을 동적으로 생성 // ---------------------------------------------------------------- // 특수한 셀 렌더링이 필요한 컬럼들을 위한 헬퍼 함수 const getCellRenderer = (accessorKey: keyof ContactPossibleItemDetail) => { switch (accessorKey) { case 'createdAt': case 'updatedAt': return function DateCell({ row }: { row: Row }) { const dateVal = row.getValue(accessorKey) as Date return formatDate(dateVal, "ko-KR") } case 'isPrimary': return function PrimaryCell({ row }: { row: Row }) { const isPrimary = row.original.isPrimary return isPrimary ? "Y" : "N" } case 'techVendorType': return function VendorTypeCell({ row }: { row: Row }) { const techVendorType = row.original.techVendorType // 벤더 타입 파싱 개선 - null/undefined 안전 처리 let types: string[] = []; if (!techVendorType) { types = []; } else if (techVendorType.startsWith('[') && techVendorType.endsWith(']')) { // JSON 배열 형태 try { const parsed = JSON.parse(techVendorType); types = Array.isArray(parsed) ? parsed.filter(Boolean) : [techVendorType]; } catch { types = [techVendorType]; } } else if (techVendorType.includes(',')) { // 콤마로 구분된 문자열 types = techVendorType.split(',').map(t => t.trim()).filter(Boolean); } else { // 단일 문자열 types = [techVendorType.trim()].filter(Boolean); } // 벤더 타입 정렬 - 조선 > 해양TOP > 해양HULL 순 const typeOrder = ["조선", "해양TOP", "해양HULL"]; types.sort((a, b) => { const indexA = typeOrder.indexOf(a); const indexB = typeOrder.indexOf(b); // 정의된 순서에 있는 경우 우선순위 적용 if (indexA !== -1 && indexB !== -1) { return indexA - indexB; } return a.localeCompare(b); }); return (
{types.length > 0 ? types.map((type, index) => ( {type} )) : ( - )}
) } case 'vendorCountry': case 'contactName': case 'contactPosition': case 'contactTitle': case 'contactEmail': case 'contactPhone': case 'contactCountry': return function OptionalCell({ row }: { row: Row }) { const value = row.original[accessorKey] return value || - } default: return function DefaultCell({ row }: { row: Row }) { return row.original[accessorKey] ?? "" } } } const baseColumns: ColumnDef[] = contactPossibleItemsColumnsConfig.map(group => ({ id: group.id, header: group.header, columns: group.columns.map(colConfig => ({ accessorKey: colConfig.accessorKey, enableResizing: colConfig.enableResizing, enableSorting: colConfig.enableSorting, size: colConfig.size, minSize: colConfig.minSize, maxSize: colConfig.maxSize, header: function HeaderCell({ column }: { column: Column }) { return }, cell: getCellRenderer(colConfig.accessorKey), })), })) // ---------------------------------------------------------------- // 4) 최종 컬럼 배열: select, baseColumns, actions // ---------------------------------------------------------------- return [ selectColumn, ...baseColumns, actionsColumn, ] }