diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-15 03:24:12 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-15 03:24:12 +0000 |
| commit | 25b916d040a512cd5248dff319d727ae144d0652 (patch) | |
| tree | ed65d637d4807ce4a1575f3080ff0df98c430ae4 /lib/pcr/table/pcr-table-column.tsx | |
| parent | 3f293c90beb58ce206a66ff444d7acfc41b56429 (diff) | |
(최겸) 구매 PCR 개발(po -> pcr, ecc pcr-confirm test 필)
Diffstat (limited to 'lib/pcr/table/pcr-table-column.tsx')
| -rw-r--r-- | lib/pcr/table/pcr-table-column.tsx | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/lib/pcr/table/pcr-table-column.tsx b/lib/pcr/table/pcr-table-column.tsx new file mode 100644 index 00000000..aa4936ce --- /dev/null +++ b/lib/pcr/table/pcr-table-column.tsx @@ -0,0 +1,416 @@ +import { ColumnDef } from "@tanstack/react-table"
+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 { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"
+import { PcrPoData, PCR_APPROVAL_STATUS_CONFIG, PCR_CHANGE_TYPE_CONFIG } from "@/lib/pcr/types"
+import { MoreHorizontal, Eye, Edit, Trash2 } from "lucide-react"
+import type { DataTableRowAction } from "@/types/table"
+import { DataTableColumnHeader } from "@/components/data-table/data-table-column-header"
+
+interface GetColumnsProps {
+ setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<PcrPoData> | null>>
+ isEvcpPage?: boolean; // EvcP 페이지인지 여부
+}
+
+export function getColumns({ setRowAction, isEvcpPage = false }: GetColumnsProps): ColumnDef<PcrPoData>[] {
+ const columns: ColumnDef<PcrPoData>[] = [
+ {
+ id: "select",
+ header: ({ table }) => (
+ <Checkbox
+ checked={table.getSelectedRowModel().rows.length > 0}
+ onCheckedChange={(value) => {
+ if (value) {
+ // 하나만 선택 가능하도록 현재 행만 선택
+ table.getRowModel().rows.forEach((row) => {
+ if (row.getIsSelected()) {
+ row.toggleSelected(false);
+ }
+ });
+ } else {
+ // 모든 선택 해제
+ table.toggleAllPageRowsSelected(false);
+ }
+ }}
+ aria-label="행 선택"
+ className="translate-y-[2px]"
+ />
+ ),
+ cell: ({ row, table }) => (
+ <Checkbox
+ checked={row.getIsSelected()}
+ onCheckedChange={(value) => {
+ if (value) {
+ // 다른 모든 행 선택 해제 후 현재 행만 선택
+ table.getRowModel().rows.forEach((r) => {
+ if (r.id !== row.id) {
+ r.toggleSelected(false);
+ }
+ });
+ }
+ row.toggleSelected(!!value);
+ }}
+ aria-label="행 선택"
+ className="translate-y-[2px]"
+ />
+ ),
+ enableSorting: false,
+ enableHiding: false,
+ },
+ {
+ accessorKey: "pcrApprovalStatus",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="PCR 승인상태" />
+ ),
+ cell: ({ row }) => {
+ const status = row.getValue("pcrApprovalStatus") as string
+ const config = PCR_APPROVAL_STATUS_CONFIG[status as keyof typeof PCR_APPROVAL_STATUS_CONFIG]
+
+ if (!config) {
+ return <Badge variant="outline">{status}</Badge>
+ }
+
+ return (
+ <Badge
+ variant={config.variant as any}
+ className={config.color}
+ >
+ {config.label}
+ </Badge>
+ )
+ },
+ filterFn: (row, id, value) => {
+ return value.includes(row.getValue(id))
+ },
+ },
+ {
+ accessorKey: "changeType",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="변경구분" />
+ ),
+ cell: ({ row }) => {
+ const changeType = row.getValue("changeType") as string
+ const config = PCR_CHANGE_TYPE_CONFIG[changeType as keyof typeof PCR_CHANGE_TYPE_CONFIG]
+
+ if (!config) {
+ return <Badge variant="outline">{changeType}</Badge>
+ }
+
+ return (
+ <Badge variant="outline">
+ {config.label}
+ </Badge>
+ )
+ },
+ filterFn: (row, id, value) => {
+ return value.includes(row.getValue(id))
+ },
+ },
+ {
+ accessorKey: "poContractNumber",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="PO/계약번호" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("poContractNumber") as string
+ return (
+ <div className="font-medium">
+ {value || "-"}
+ </div>
+ )
+ },
+ },
+ {
+ accessorKey: "project",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="프로젝트" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("project") as string
+ return (
+ <div className="max-w-[200px] truncate" title={value}>
+ {value || "-"}
+ </div>
+ )
+ },
+ },
+ {
+ accessorKey: "pcrRequestDate",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="PCR 요청일자" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("pcrRequestDate") as Date
+ if (!value) return "-"
+
+ return (
+ <div className="text-sm">
+ {value.toLocaleDateString('ko-KR', {
+ year: 'numeric',
+ month: '2-digit',
+ day: '2-digit'
+ })}
+ </div>
+ )
+ },
+ },
+ {
+ accessorKey: "revItemNumber",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="Rev./품번" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("revItemNumber") as string
+ return (
+ <div className="max-w-[150px] truncate" title={value}>
+ {value || "-"}
+ </div>
+ )
+ },
+ },
+ {
+ accessorKey: "purchaseContractManager",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="구매/계약담당자" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("purchaseContractManager") as string
+ return (
+ <div className="max-w-[120px] truncate" title={value}>
+ {value || "-"}
+ </div>
+ )
+ },
+ },
+ {
+ accessorKey: "pcrCreator",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="PCR 생성자" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("pcrCreator") as string
+ return (
+ <div className="max-w-[120px] truncate" title={value}>
+ {value || "-"}
+ </div>
+ )
+ },
+ },
+ {
+ accessorKey: "poContractAmountBefore",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="PO/계약금액(전)" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("poContractAmountBefore") as number
+ const currency = row.original.contractCurrency
+
+ if (!value) return "-"
+
+ return (
+ <div className="text-right font-mono text-sm">
+ {currency} {value.toLocaleString()}
+ </div>
+ )
+ },
+ },
+ {
+ accessorKey: "poContractAmountAfter",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="PO/계약금액(후)" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("poContractAmountAfter") as number
+ const currency = row.original.contractCurrency
+
+ if (!value) return "-"
+
+ return (
+ <div className="text-right font-mono text-sm">
+ {currency} {value.toLocaleString()}
+ </div>
+ )
+ },
+ },
+ {
+ accessorKey: "contractCurrency",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="계약통화" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("contractCurrency") as string
+ return (
+ <div className="text-center">
+ {value || "-"}
+ </div>
+ )
+ },
+ },
+ // EvcP 페이지에서만 협력업체 정보 표시
+ ...(isEvcpPage ? [{
+ accessorKey: "vendorName" as const,
+ header: ({ column }: { column: any }) => (
+ <DataTableColumnHeaderSimple column={column} title="협력업체" />
+ ),
+ cell: ({ row }: { row: any }) => {
+ const vendorName = row.getValue("vendorName") as string
+ const vendorCode = row.original.vendorCode as string
+ const displayText = vendorName
+ ? vendorCode
+ ? `${vendorName} (${vendorCode})`
+ : vendorName
+ : "-"
+
+ return (
+ <div className="max-w-[150px] truncate" title={displayText}>
+ {displayText}
+ </div>
+ )
+ },
+ }] : []),
+ {
+ accessorKey: "details",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="상세" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("details") as string
+ return (
+ <div className="max-w-[200px] truncate" title={value}>
+ {value || "-"}
+ </div>
+ )
+ },
+ },
+ {
+ accessorKey: "pcrReason",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="PCR 사유" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("pcrReason") as string
+ return (
+ <div className="max-w-[150px] truncate" title={value}>
+ {value || "-"}
+ </div>
+ )
+ },
+ },
+ {
+ accessorKey: "detailsReason",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="상세 사유" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("detailsReason") as string
+ return (
+ <div className="max-w-[150px] truncate" title={value}>
+ {value || "-"}
+ </div>
+ )
+ },
+ },
+ {
+ accessorKey: "rejectionReason",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="거절 사유" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("rejectionReason") as string
+ return (
+ <div className="max-w-[150px] truncate" title={value}>
+ {value || "-"}
+ </div>
+ )
+ },
+ },
+ {
+ accessorKey: "pcrResponseDate",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="PCR 회신일" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("pcrResponseDate") as Date
+ if (!value) return "-"
+
+ return (
+ <div className="text-sm">
+ {value.toLocaleDateString('ko-KR', {
+ year: 'numeric',
+ month: '2-digit',
+ day: '2-digit'
+ })}
+ </div>
+ )
+ },
+ },
+ {
+ accessorKey: "createdAt",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="생성일" />
+ ),
+ cell: ({ row }) => {
+ const value = row.getValue("createdAt") as Date
+ if (!value) return "-"
+
+ return (
+ <div className="text-sm">
+ {value.toLocaleDateString('ko-KR', {
+ year: 'numeric',
+ month: '2-digit',
+ day: '2-digit'
+ })}
+ </div>
+ )
+ },
+ },
+ {
+ id: "actions",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="작업" />
+ ),
+ cell: ({ row }) => {
+ const pcrPo = row.original
+
+ return (
+ <DropdownMenu>
+ <DropdownMenuTrigger asChild>
+ <Button
+ variant="ghost"
+ className="flex size-8 p-0 data-[state=open]:bg-muted"
+ >
+ <MoreHorizontal className="size-4" />
+ <span className="sr-only">메뉴 열기</span>
+ </Button>
+ </DropdownMenuTrigger>
+ <DropdownMenuContent align="end" className="w-[160px]">
+ <DropdownMenuLabel>작업</DropdownMenuLabel>
+ <DropdownMenuSeparator />
+
+ <DropdownMenuItem
+ onClick={() => setRowAction({ row, type: "update" })}
+ >
+ <Edit className="mr-2 size-4" />
+ 수정
+ </DropdownMenuItem>
+
+ </DropdownMenuContent>
+ </DropdownMenu>
+ )
+ },
+ enableSorting: false,
+ enableHiding: false,
+ },
+ ]
+
+ return columns
+}
|
