diff options
Diffstat (limited to 'lib/po/vendor-table/shi-vendor-po-columns.tsx')
| -rw-r--r-- | lib/po/vendor-table/shi-vendor-po-columns.tsx | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/lib/po/vendor-table/shi-vendor-po-columns.tsx b/lib/po/vendor-table/shi-vendor-po-columns.tsx new file mode 100644 index 00000000..041e0c05 --- /dev/null +++ b/lib/po/vendor-table/shi-vendor-po-columns.tsx @@ -0,0 +1,462 @@ +"use client" + +import * as React from "react" +import { type ColumnDef } from "@tanstack/react-table" +import { + SendIcon, + FileTextIcon, + MoreHorizontalIcon, +} from "lucide-react" + +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" +import { Checkbox } from "@/components/ui/checkbox" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + 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 { VendorPO } from "./types" + +// 서명 요청 전용 액션 타입 +type ShiVendorPORowAction = { + row: { original: VendorPO } + type: "view-items" | "signature-request" +} + +interface GetShiVendorColumnsProps { + setRowAction: React.Dispatch<React.SetStateAction<ShiVendorPORowAction | null>> + selectedRows: number[] + onRowSelect: (id: number, selected: boolean) => void +} + +export function getShiVendorColumns({ + setRowAction, + selectedRows, + onRowSelect, +}: GetShiVendorColumnsProps): ColumnDef<VendorPO>[] { + return [ + // 선택 체크박스 (1개만 선택 가능) + { + id: "select", + header: () => <div className="text-center">선택</div>, + cell: ({ row }) => ( + <div className="flex justify-center"> + <Checkbox + checked={selectedRows.includes(row.original.id)} + onCheckedChange={(checked) => { + onRowSelect(row.original.id, !!checked) + }} + aria-label="행 선택" + /> + </div> + ), + enableSorting: false, + enableHiding: false, + size: 40, + }, + + // No. (ID) + { + accessorKey: "id", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="No." /> + ), + cell: ({ row }) => { + const id = row.getValue("id") as number + return <div className="text-sm font-mono">{id}</div> + }, + size: 60, + }, + + // PO/계약번호 + { + accessorKey: "contractNo", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="PO/계약번호" /> + ), + cell: ({ row }) => { + const contractNo = row.getValue("contractNo") as string + return ( + <div className="font-medium"> + {contractNo} + </div> + ) + }, + size: 120, + }, + + // Rev. / 품번 (PO 버전) + { + accessorKey: "poVersion", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="Rev. / 품번" /> + ), + cell: ({ row }) => { + const version = row.getValue("poVersion") as number + return <div className="text-sm font-medium">{version || '-'}</div> + }, + size: 80, + }, + + // 계약상태 + { + accessorKey: "contractStatus", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="계약상태" /> + ), + cell: ({ row }) => { + const status = row.getValue("contractStatus") as string + return ( + <Badge variant="outline"> + {status || '-'} + </Badge> + ) + }, + size: 100, + }, + + // 계약종류 + { + accessorKey: "contractType", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="계약종류" /> + ), + cell: ({ row }) => { + const type = row.getValue("contractType") as string + return <Badge variant="outline">{type || '-'}</Badge> + }, + size: 100, + }, + + // 상세품목 (버튼) + { + id: "itemsAction", + header: () => <div className="text-center">상세품목</div>, + cell: ({ row }) => ( + <div className="flex justify-center"> + <Button + variant="outline" + size="sm" + className="h-8 px-2" + onClick={() => setRowAction({ row, type: "view-items" })} + > + <FileTextIcon className="h-3.5 w-3.5 mr-1" /> + 보기 + </Button> + </div> + ), + enableSorting: false, + size: 80, + }, + + // 프로젝트 + { + accessorKey: "projectName", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="프로젝트" /> + ), + cell: ({ row }) => { + const projectName = row.getValue("projectName") as string + return ( + <div className="max-w-[150px] truncate" title={projectName}> + {projectName || '-'} + </div> + ) + }, + size: 150, + }, + + // 계약명/자재내역 + { + accessorKey: "contractName", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="계약명/자재내역" /> + ), + cell: ({ row }) => { + const contractName = row.getValue("contractName") as string + return ( + <div className="max-w-[200px] truncate" title={contractName}> + {contractName || '-'} + </div> + ) + }, + size: 200, + }, + + // PO/계약기간 + { + accessorKey: "contractPeriod", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="PO/계약기간" /> + ), + cell: ({ row }) => { + const period = row.getValue("contractPeriod") as string + return ( + <div className="text-sm whitespace-nowrap"> + {period || '-'} + </div> + ) + }, + size: 150, + }, + + // PO/계약금액 + { + accessorKey: "totalAmount", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="PO/계약금액" /> + ), + cell: ({ row }) => { + const amount = row.getValue("totalAmount") as string | number + return <div className="text-sm text-right font-mono">{amount || '-'}</div> + }, + size: 120, + }, + + // 계약통화 + { + accessorKey: "currency", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="계약통화" /> + ), + cell: ({ row }) => { + const currency = row.getValue("currency") as string + return <div className="text-sm font-mono">{currency || '-'}</div> + }, + size: 80, + }, + + // 지불조건 + { + accessorKey: "paymentTerms", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="지불조건" /> + ), + cell: ({ row }) => { + const terms = row.getValue("paymentTerms") as string + return ( + <div className="max-w-[120px] truncate text-sm" title={terms}> + {terms || '-'} + </div> + ) + }, + size: 120, + }, + + // Tax + { + accessorKey: "tax", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="Tax" /> + ), + cell: ({ row }) => { + const tax = row.getValue("tax") as string + return <div className="text-sm">{tax || '-'}</div> + }, + size: 80, + }, + + // 환율 + { + accessorKey: "exchangeRate", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="환율" /> + ), + cell: ({ row }) => { + const rate = row.getValue("exchangeRate") as string + return <div className="text-sm font-mono">{rate || '-'}</div> + }, + size: 100, + }, + + // 인도조건 + { + accessorKey: "deliveryTerms", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="인도조건" /> + ), + cell: ({ row }) => { + const terms = row.getValue("deliveryTerms") as string + return <div className="text-sm">{terms || '-'}</div> + }, + size: 100, + }, + + // 구매/계약담당 + { + accessorKey: "purchaseManager", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="구매/계약담당" /> + ), + cell: ({ row }) => { + const manager = row.getValue("purchaseManager") as string + return <div className="text-sm">{manager || '-'}</div> + }, + size: 120, + }, + + // PO/계약수신일 + { + accessorKey: "poReceiveDate", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="PO/계약수신일" /> + ), + cell: ({ row }) => { + const date = row.getValue("poReceiveDate") as string + return <div className="text-sm">{date || '-'}</div> + }, + size: 120, + }, + + // 계약체결일 + { + accessorKey: "contractDate", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="계약체결일" /> + ), + cell: ({ row }) => { + const date = row.getValue("contractDate") as string + return <div className="text-sm">{date || '-'}</div> + }, + size: 120, + }, + + // L/C No. + { + accessorKey: "lcNo", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="L/C No." /> + ), + cell: ({ row }) => { + const lcNo = row.getValue("lcNo") as string + return <div className="text-sm">{lcNo || '-'}</div> + }, + size: 120, + }, + + // 납품대금 연동제 대상 + { + accessorKey: "priceIndexTarget", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="납품대금 연동제 대상" /> + ), + cell: ({ row }) => { + const target = row.getValue("priceIndexTarget") as string | boolean + return <div className="text-sm">{target?.toString() || '-'}</div> + }, + size: 140, + }, + + // 연계 PO/계약번호 + { + accessorKey: "linkedContractNo", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="연계 PO/계약번호" /> + ), + cell: ({ row }) => { + const linkedNo = row.getValue("linkedContractNo") as string + return <div className="text-sm">{linkedNo || '-'}</div> + }, + size: 140, + }, + + // 최종수정일 + { + accessorKey: "lastModifiedDate", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="최종수정일" /> + ), + cell: ({ row }) => { + const date = row.getValue("lastModifiedDate") as string + return <div className="text-sm">{date || '-'}</div> + }, + size: 120, + }, + + // 최종수정자 + { + accessorKey: "lastModifiedBy", + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="최종수정자" /> + ), + cell: ({ row }) => { + const user = row.getValue("lastModifiedBy") as string + return <div className="text-sm">{user || '-'}</div> + }, + size: 120, + }, + + // 액션 컬럼 (서명 요청 중심) + { + id: "actions", + enableHiding: false, + header: () => <div className="text-center">Actions</div>, + cell: ({ row }) => { + return ( + <div className="flex items-center justify-center gap-2"> + {/* 서명 요청 버튼 */} + <TooltipProvider> + <Tooltip> + <TooltipTrigger asChild> + <Button + variant="outline" + size="sm" + className="h-8 px-2 text-blue-600 border-blue-200 hover:bg-blue-50" + onClick={() => setRowAction({ row, type: "signature-request" })} + > + <SendIcon className="h-3.5 w-3.5 mr-1" aria-hidden="true" /> + 서명 요청 + </Button> + </TooltipTrigger> + <TooltipContent> + 벤더에게 전자서명 요청 + </TooltipContent> + </Tooltip> + </TooltipProvider> + + {/* 드롭다운 메뉴 (추가 액션) + <DropdownMenu> + <DropdownMenuTrigger asChild> + <Button variant="ghost" className="h-8 w-8 p-0"> + <span className="sr-only">Open menu</span> + <MoreHorizontalIcon className="h-4 w-4" /> + </Button> + </DropdownMenuTrigger> + <DropdownMenuContent align="end"> + <DropdownMenuLabel>액션</DropdownMenuLabel> + <DropdownMenuItem + onClick={() => setRowAction({ row, type: "view-items" })} + > + <FileTextIcon className="mr-2 h-4 w-4" /> + 상세품목 보기 + </DropdownMenuItem> + <DropdownMenuSeparator /> + <DropdownMenuItem + onClick={() => setRowAction({ row, type: "signature-request" })} + className="text-blue-600" + > + <SendIcon className="mr-2 h-4 w-4" /> + 서명 요청 + </DropdownMenuItem> + </DropdownMenuContent> + </DropdownMenu> */} + </div> + ) + }, + size: 160, + minSize: 160, + }, + ] +}
\ No newline at end of file |
