From bcd462d6e60871b86008e072f4b914138fc5c328 Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Mon, 11 Aug 2025 09:34:40 +0000
Subject: (김준회) 리치텍스트에디터 (결재템플릿을 위한 공통컴포넌트),
 command-menu 에러 수정, 결재 템플릿 관리, 결재선 관리, ECC RFQ+PR Item 수신시
 비즈니스테이블(ProcurementRFQ) 데이터 적재, WSDL 오류 수정
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../table/approval-line-table-columns.tsx          | 197 +++++++++++++++++++++
 1 file changed, 197 insertions(+)
 create mode 100644 lib/approval-line/table/approval-line-table-columns.tsx

(limited to 'lib/approval-line/table/approval-line-table-columns.tsx')

diff --git a/lib/approval-line/table/approval-line-table-columns.tsx b/lib/approval-line/table/approval-line-table-columns.tsx
new file mode 100644
index 00000000..5b35b92c
--- /dev/null
+++ b/lib/approval-line/table/approval-line-table-columns.tsx
@@ -0,0 +1,197 @@
+"use client"
+
+import * as React from "react"
+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 { DataTableColumnHeader } from "@/components/data-table/data-table-column-header"
+import {
+  DropdownMenu,
+  DropdownMenuContent,
+  DropdownMenuItem,
+  DropdownMenuSeparator,
+  DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu"
+import { type ApprovalLine } from "../service"
+import { formatApprovalLine } from "../utils/format"
+import { formatDate } from "@/lib/utils"
+import { MoreHorizontal, Copy, Edit, Trash2 } from "lucide-react"
+
+interface GetColumnsProps {
+  setRowAction: React.Dispatch<React.SetStateAction<{
+    type: "update" | "delete" | "duplicate";
+    row: { original: ApprovalLine };
+  } | null>>;
+}
+
+
+export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<ApprovalLine>[] {
+  return [
+    {
+      id: "select",
+      header: ({ table }) => (
+        <Checkbox
+          checked={
+            table.getIsAllPageRowsSelected() ||
+            (table.getIsSomePageRowsSelected() && "indeterminate")
+          }
+          onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
+          aria-label="Select all"
+          className="translate-y-[2px]"
+        />
+      ),
+      cell: ({ row }) => (
+        <Checkbox
+          checked={row.getIsSelected()}
+          onCheckedChange={(value) => row.toggleSelected(!!value)}
+          aria-label="Select row"
+          className="translate-y-[2px]"
+        />
+      ),
+      enableSorting: false,
+      enableHiding: false,
+    },
+    {
+      accessorKey: "name",
+      header: ({ column }) => (
+        <DataTableColumnHeader column={column} title="결재선 이름" />
+      ),
+      cell: ({ row }) => {
+        return (
+          <div className="flex space-x-2">
+            <span className="max-w-[500px] truncate font-medium">
+              {row.getValue("name")}
+            </span>
+          </div>
+        )
+      },
+    },
+    {
+      accessorKey: "description",
+      header: ({ column }) => (
+        <DataTableColumnHeader column={column} title="설명" />
+      ),
+      cell: ({ row }) => {
+        return (
+          <div className="flex space-x-2">
+            <span className="max-w-[500px] truncate">
+              {row.getValue("description") || "-"}
+            </span>
+          </div>
+        )
+      },
+    },
+    {
+      accessorKey: "aplns",
+      header: ({ column }) => (
+        <DataTableColumnHeader column={column} title="결재선" />
+      ),
+      cell: ({ row }) => {
+        const aplns = row.getValue("aplns") as unknown as Array<{
+          seq: string;
+          name?: string;
+          emailAddress?: string;
+          role: string;
+        }>;
+        const approvalLineText = formatApprovalLine(aplns);
+        
+        return (
+          <div className="flex space-x-2">
+            <div className="flex flex-col gap-1">
+              <div className="max-w-[400px] truncate text-sm">
+                {approvalLineText}
+                <Badge variant="secondary" className="w-fit">
+                  {aplns?.length || 0}명
+                </Badge>
+              </div>
+            </div>
+          </div>
+        )
+      },
+    },
+    {
+      accessorKey: "createdAt",
+      header: ({ column }) => (
+        <DataTableColumnHeader column={column} title="생성일" />
+      ),
+      cell: ({ row }) => {
+        return (
+          <div className="flex space-x-2">
+            <span className="max-w-[500px] truncate">
+              {formatDate(row.getValue("createdAt"))}
+            </span>
+          </div>
+        )
+      },
+    },
+    {
+      accessorKey: "updatedAt",
+      header: ({ column }) => (
+        <DataTableColumnHeader column={column} title="수정일" />
+      ),
+      cell: ({ row }) => {
+        return (
+          <div className="flex space-x-2">
+            <span className="max-w-[500px] truncate">
+              {formatDate(row.getValue("updatedAt"))}
+            </span>
+          </div>
+        )
+      },
+    },
+    {
+      id: "actions",
+      cell: ({ row }) => {
+
+        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
+                onClick={() => {
+                  setRowAction({ type: "update", row });
+                }}
+              >
+                <Edit className="mr-2 size-4" aria-hidden="true" />
+                수정하기
+              </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"
+              >
+                <Trash2 className="mr-2 size-4" aria-hidden="true" />
+                삭제하기
+              </DropdownMenuItem>
+            </DropdownMenuContent>
+          </DropdownMenu>
+        );
+      },
+      enableSorting: false,
+      enableHiding: false,
+      size: 80,
+    },
+  ]
+} 
\ No newline at end of file
-- 
cgit v1.2.3

