"use client" import * as React from "react" import { type DataTableRowAction } from "@/types/table" import { type ColumnDef } from "@tanstack/react-table" import { Download, Ellipsis, Paperclip, CheckCircle, XCircle, Eye } from "lucide-react" import { toast } from "sonner" import { getErrorMessage } from "@/lib/handle-error" import { formatDate, formatDateTime } 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, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" import { scopeHelpers } from "@/config/basicContractColumnsConfig" import { BasicContractTemplate } from "@/db/schema" import { quickDownload } from "@/lib/file-download" import { useRouter } from "next/navigation" interface GetColumnsProps { setRowAction: React.Dispatch | null>> router: ReturnType } /** * 파일 다운로드 함수 (공용 유틸리티 사용) */ const handleFileDownload = async (filePath: string, fileName: string) => { try { await quickDownload(filePath, fileName); } catch (error) { console.error("파일 다운로드 오류:", error); toast.error("파일 다운로드 중 오류가 발생했습니다."); } }; /** * 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" /> ), maxSize: 30, enableSorting: false, enableHiding: false, } // ---------------------------------------------------------------- // 2) 파일 다운로드 컬럼 (아이콘) // ---------------------------------------------------------------- const downloadColumn: ColumnDef = { id: "download", header: "", cell: ({ row }) => { const template = row.original; return ( ); }, maxSize: 30, enableSorting: false, } // ---------------------------------------------------------------- // 3) actions 컬럼 (Dropdown 메뉴) // ---------------------------------------------------------------- const actionsColumn: ColumnDef = { id: "actions", enableHiding: false, cell: function Cell({ row }) { const [isUpdatePending, startUpdateTransition] = React.useTransition() const template = row.original; const handleViewDetails = () => { router.push(`/evcp/basic-contract-template/${template.id}`); }; return ( View Details setRowAction({ row, type: "update" })} > Edit {template.status === 'ACTIVE' && ( setRowAction({ row, type: "dispose" })} > Dispose )} {template.status === 'DISPOSED' && template.disposedAt && ( setRowAction({ row, type: "restore" })} > Restore )} setRowAction({ row, type: "delete" })} > Delete ⌘⌫ ) }, maxSize: 30, } // ---------------------------------------------------------------- // 4) 직접 컬럼 정의 (그룹별로 중첩) // ---------------------------------------------------------------- // 기본 정보 그룹 const basicInfoColumns: ColumnDef[] = [ { accessorKey: "status", header: ({ column }) => , cell: ({ row }) => { const status = row.getValue("status") as string; const isActive = status === "ACTIVE"; return ( {isActive ? "활성" : "폐기"} ); }, size: 80, enableResizing: true, }, { accessorKey: "templateName", header: ({ column }) => , cell: ({ row }) => { const template = row.original; const handleClick = () => { router.push(`/evcp/basic-contract-template/${template.id}`); }; return (
); }, size: 250, enableResizing: true, }, { accessorKey: "revision", header: ({ column }) => , cell: ({ row }) => { const template = row.original; return ( v{template.revision} ); }, size: 60, enableResizing: true, }, { accessorKey: "legalReviewRequired", header: ({ column }) => , cell: ({ row }) => { const required = row.getValue("legalReviewRequired") as boolean; return ( {required ? "필요" : "불필요"} ); }, size: 100, enableResizing: true, }, ]; // 적용 범위 그룹 const scopeColumns: ColumnDef[] = [ { accessorKey: "shipBuildingApplicable", header: ({ column }) => , cell: ({ row }) => { const applicable = row.getValue("shipBuildingApplicable") as boolean; return (
{applicable ? ( ) : ( )}
); }, size: 80, enableResizing: true, }, { accessorKey: "windApplicable", header: ({ column }) => , cell: ({ row }) => { const applicable = row.getValue("windApplicable") as boolean; return (
{applicable ? ( ) : ( )}
); }, size: 60, enableResizing: true, }, { accessorKey: "pcApplicable", header: ({ column }) => , cell: ({ row }) => { const applicable = row.getValue("pcApplicable") as boolean; return (
{applicable ? ( ) : ( )}
); }, size: 50, enableResizing: true, }, { accessorKey: "nbApplicable", header: ({ column }) => , cell: ({ row }) => { const applicable = row.getValue("nbApplicable") as boolean; return (
{applicable ? ( ) : ( )}
); }, size: 50, enableResizing: true, }, { accessorKey: "rcApplicable", header: ({ column }) => , cell: ({ row }) => { const applicable = row.getValue("rcApplicable") as boolean; return (
{applicable ? ( ) : ( )}
); }, size: 50, enableResizing: true, }, { accessorKey: "gyApplicable", header: ({ column }) => , cell: ({ row }) => { const applicable = row.getValue("gyApplicable") as boolean; return (
{applicable ? ( ) : ( )}
); }, size: 50, enableResizing: true, }, { accessorKey: "sysApplicable", header: ({ column }) => , cell: ({ row }) => { const applicable = row.getValue("sysApplicable") as boolean; return (
{applicable ? ( ) : ( )}
); }, size: 60, enableResizing: true, }, { accessorKey: "infraApplicable", header: ({ column }) => , cell: ({ row }) => { const applicable = row.getValue("infraApplicable") as boolean; return (
{applicable ? ( ) : ( )}
); }, size: 60, enableResizing: true, }, ]; // 파일 정보 그룹 const fileInfoColumns: ColumnDef[] = [ { accessorKey: "fileName", header: ({ column }) => , cell: ({ row }) => { const fileName = row.getValue("fileName") as string; return (
{fileName}
); }, size: 200, enableResizing: true, }, ]; // 감사 정보 그룹 const auditColumns: ColumnDef[] = [ { accessorKey: "createdAt", header: ({ column }) => , cell: ({ row }) => { const date = row.getValue("createdAt") as Date; return date ? formatDateTime(date, "KR") : "-"; }, size: 120, enableResizing: true, }, { accessorKey: "updatedAt", header: ({ column }) => , cell: ({ row }) => { const date = row.getValue("updatedAt") as Date; return date ? formatDateTime(date, "KR") : "-"; }, size: 120, enableResizing: true, }, { accessorKey: "disposedAt", header: ({ column }) => , cell: ({ row }) => { const date = row.getValue("disposedAt") as Date; return date ? formatDateTime(date, "KR") : "-"; }, size: 120, enableResizing: true, }, { accessorKey: "restoredAt", header: ({ column }) => , cell: ({ row }) => { const date = row.getValue("restoredAt") as Date; return date ? formatDateTime(date, "KR") : "-"; }, size: 120, enableResizing: true, }, ]; // 중첩 컬럼 그룹 생성 const nestedColumns: ColumnDef[] = [ { id: "기본 정보", header: "기본 정보", columns: basicInfoColumns, }, { id: "적용 범위", header: "적용 범위", columns: scopeColumns, }, { id: "파일 정보", header: "파일 정보", columns: fileInfoColumns, }, { id: "감사 정보", header: "감사 정보", columns: auditColumns, }, ] // ---------------------------------------------------------------- // 5) 최종 컬럼 배열: select, download, nestedColumns, actions // ---------------------------------------------------------------- return [ selectColumn, downloadColumn, ...nestedColumns, actionsColumn, ] }