diff options
| author | joonhoekim <26rote@gmail.com> | 2025-08-11 09:34:40 +0000 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-08-11 09:34:40 +0000 |
| commit | bcd462d6e60871b86008e072f4b914138fc5c328 (patch) | |
| tree | c22876fd6c6e7e48254587848b9dff50cdb8b032 /lib/approval-template/table/approval-template-table-columns.tsx | |
| parent | cbb4c7fe0b94459162ad5e998bc05cd293e0ff96 (diff) | |
(김준회) 리치텍스트에디터 (결재템플릿을 위한 공통컴포넌트), command-menu 에러 수정, 결재 템플릿 관리, 결재선 관리, ECC RFQ+PR Item 수신시 비즈니스테이블(ProcurementRFQ) 데이터 적재, WSDL 오류 수정
Diffstat (limited to 'lib/approval-template/table/approval-template-table-columns.tsx')
| -rw-r--r-- | lib/approval-template/table/approval-template-table-columns.tsx | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/lib/approval-template/table/approval-template-table-columns.tsx b/lib/approval-template/table/approval-template-table-columns.tsx new file mode 100644 index 00000000..8447c7d2 --- /dev/null +++ b/lib/approval-template/table/approval-template-table-columns.tsx @@ -0,0 +1,165 @@ +"use client" + +import * as React from 'react'; +import { type ColumnDef } from '@tanstack/react-table'; +import { MoreHorizontal, Copy, Trash, Eye } from 'lucide-react'; +import Link from 'next/link'; + +import { Checkbox } from '@/components/ui/checkbox'; +import { Button } from '@/components/ui/button'; +import { Badge } from '@/components/ui/badge'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from '@/components/ui/dropdown-menu'; +import { formatDate } from '@/lib/utils'; +import { DataTableColumnHeaderSimple } from '@/components/data-table/data-table-column-simple-header'; +import { type ApprovalTemplate } from '@/lib/approval-template/service'; +import { type DataTableRowAction } from '@/types/table'; + +interface GetColumnsProps { + setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<ApprovalTemplate> | null>> +} + +export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<ApprovalTemplate>[] { + return [ + { + 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" + /> + ), + enableSorting: false, + enableHiding: false, + }, + { + accessorKey: 'name', + header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="템플릿 이름" />, + cell: ({ row: _row }) => { + const t = _row.original; + return ( + <div className="flex flex-col gap-1"> + <span className="font-medium">{t.name}</span> + {t.description && ( + <div className="text-xs text-muted-foreground line-clamp-2">{t.description}</div> + )} + </div> + ); + }, + enableSorting: true, + enableHiding: false, + size: 220, + }, + { + accessorKey: 'subject', + header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="제목" />, + cell: ({ getValue }) => { + const subject = getValue() as string; + return <div className="text-sm text-muted-foreground">{subject}</div>; + }, + enableSorting: true, + size: 250, + }, + { + accessorKey: 'category', + header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="카테고리" />, + cell: ({ getValue }) => { + const category = getValue() as string | null; + if (!category) return <div>-</div>; + return <Badge variant="outline">{category}</Badge>; + }, + enableSorting: true, + size: 120, + }, + { + accessorKey: 'createdAt', + header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="생성일" />, + cell: ({ cell }) => { + const date = cell.getValue() as Date; + return <div className="text-sm text-muted-foreground">{formatDate(date)}</div>; + }, + enableSorting: true, + size: 200, + }, + { + accessorKey: 'updatedAt', + header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="수정일" />, + cell: ({ cell }) => { + const date = cell.getValue() as Date; + return <div className="text-sm text-muted-foreground">{formatDate(date)}</div>; + }, + enableSorting: true, + size: 200, + }, + { + id: 'actions', + cell: ({ row }) => { + const template = row.original; + + return ( + <DropdownMenu> + <DropdownMenuTrigger asChild> + <Button + aria-label="Open menu" + variant="ghost" + className="flex size-8 p-0 data-[state=open]:bg-muted" + > + <MoreHorizontal className="size-4" aria-hidden="true" /> + </Button> + </DropdownMenuTrigger> + <DropdownMenuContent align="end" className="w-40"> + <DropdownMenuItem asChild> + <Link href={`/evcp/approval/template/${template.id}`}> + <Eye className="mr-2 size-4" aria-hidden="true" /> + 상세 보기 + </Link> + </DropdownMenuItem> + + <DropdownMenuItem + onClick={() => { + setRowAction({ type: 'duplicate', row }); + }} + > + <Copy className="mr-2 size-4" aria-hidden="true" /> + 복제하기 + </DropdownMenuItem> + + <DropdownMenuSeparator /> + + <DropdownMenuItem + onClick={() => { + setRowAction({ type: 'delete', row }); + }} + className="text-destructive focus:text-destructive" + > + <Trash className="mr-2 size-4" aria-hidden="true" /> + 삭제하기 + </DropdownMenuItem> + </DropdownMenuContent> + </DropdownMenu> + ); + }, + enableSorting: false, + enableHiding: false, + size: 80, + }, + ]; +}
\ No newline at end of file |
