diff options
Diffstat (limited to 'lib/compliance/responses/compliance-responses-columns.tsx')
| -rw-r--r-- | lib/compliance/responses/compliance-responses-columns.tsx | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/lib/compliance/responses/compliance-responses-columns.tsx b/lib/compliance/responses/compliance-responses-columns.tsx new file mode 100644 index 00000000..c9596ae5 --- /dev/null +++ b/lib/compliance/responses/compliance-responses-columns.tsx @@ -0,0 +1,189 @@ +"use client"; + +import * as React from "react"; +import { type ColumnDef } from "@tanstack/react-table"; +import { format } from "date-fns"; +import { ko } from "date-fns/locale"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { Checkbox } from "@/components/ui/checkbox"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, + DropdownMenuShortcut, +} from "@/components/ui/dropdown-menu"; +import { MoreHorizontal, Eye, Download, Trash2 } from "lucide-react"; +import type { DataTableRowAction } from "@/types/table"; +import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"; + +interface GetResponseColumnsProps { + setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<any> | null>>; +} + +export function getResponseColumns({ setRowAction }: GetResponseColumnsProps): ColumnDef<any>[] { + // ---------------------------------------------------------------- + // 1) select 컬럼 (체크박스) + // ---------------------------------------------------------------- + const selectColumn: ColumnDef<any> = { + id: "select", + header: ({ table }) => ( + <Checkbox + checked={ + table.getIsAllPageRowsSelected() || + (table.getIsSomePageRowsSelected() && "indeterminate") + } + onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)} + aria-label="Select all" + className="translate-y-0.5" + /> + ), + cell: ({ row }) => ( + <Checkbox + checked={row.getIsSelected()} + onCheckedChange={(value) => row.toggleSelected(!!value)} + aria-label="Select row" + className="translate-y-0.5" + /> + ), + size: 40, + enableSorting: false, + enableHiding: false, + }; + + // ---------------------------------------------------------------- + // 2) actions 컬럼 (Dropdown 메뉴) + // ---------------------------------------------------------------- + const actionsColumn: ColumnDef<any> = { + id: "actions", + header: "작업", + enableHiding: false, + cell: ({ row }) => { + const response = row.original; + + return ( + <DropdownMenu> + <DropdownMenuTrigger asChild> + <Button variant="ghost" className="h-8 w-8 p-0"> + <span className="sr-only">메뉴 열기</span> + <MoreHorizontal className="h-4 w-4" /> + </Button> + </DropdownMenuTrigger> + <DropdownMenuContent align="end"> + <DropdownMenuItem onClick={() => window.location.href = `/evcp/compliance/${response.templateId}/responses/${response.id}`}> + <Eye className="mr-2 h-4 w-4" /> + Detail + </DropdownMenuItem> + <DropdownMenuItem onClick={() => setRowAction({ type: 'delete', row: row })}> + <Trash2 className="mr-2 h-4 w-4" /> + Delete + <DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut> + </DropdownMenuItem> + </DropdownMenuContent> + </DropdownMenu> + ); + }, + size: 40, + }; + + // ---------------------------------------------------------------- + // 3) 일반 컬럼들 (정렬 가능) + // ---------------------------------------------------------------- + const dataColumns: ColumnDef<any>[] = [ + { + accessorKey: "templateName", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="템플릿명" /> + ), + cell: ({ row }) => ( + <div className="font-medium">{row.getValue("templateName")}</div> + ), + enableResizing: true, + }, + { + accessorKey: "vendorId", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="Vendor ID" /> + ), + cell: ({ row }) => ( + <div className="font-medium">{row.getValue("vendorId") || '-'}</div> + ), + enableResizing: true, + }, + { + accessorKey: "vendorName", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="업체명" /> + ), + cell: ({ row }) => ( + <div className="font-medium">{row.getValue("vendorName") || '-'}</div> + ), + enableResizing: true, + }, + { + accessorKey: "contractName", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="계약서명" /> + ), + cell: ({ row }) => ( + <div className="font-medium">{row.getValue("contractName") || '-'}</div> + ), + enableResizing: true, + }, + { + accessorKey: "status", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="상태" /> + ), + cell: ({ row }) => { + const status = row.getValue("status") as string; + const getStatusBadge = (status: string) => { + switch (status) { + case "COMPLETED": + return <Badge variant="default">제출완료</Badge>; + case "IN_PROGRESS": + return <Badge variant="secondary">진행중</Badge>; + case "REVIEWED": + return <Badge variant="outline">검토완료</Badge>; + default: + return <Badge variant="secondary">{status}</Badge>; + } + }; + return getStatusBadge(status); + }, + enableResizing: true, + }, + { + accessorKey: "reviewerName", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="검토자" /> + ), + cell: ({ row }) => { + const reviewerName = row.getValue("reviewerName") as string; + return reviewerName || '-'; + }, + enableResizing: true, + }, + { + accessorKey: "reviewedAt", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="검토일시" /> + ), + cell: ({ row }) => { + const date = row.getValue("reviewedAt") as Date; + return date ? format(new Date(date), 'yyyy-MM-dd HH:mm', { locale: ko }) : '-'; + }, + enableResizing: true, + }, + ]; + + // ---------------------------------------------------------------- + // 4) 최종 컬럼 배열: select, dataColumns, actions + // ---------------------------------------------------------------- + return [ + selectColumn, + ...dataColumns, + actionsColumn, + ]; +} |
