From 281a4060cff0396253192f4e852be6770ad97cbd Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Thu, 27 Mar 2025 18:50:59 +0900
Subject: feat: POA 관련 파일 추가 및 contract 스키마 수정
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/poa/table/poa-table-columns.tsx | 165 ++++++++++++++++++++++++++++++++++++
 1 file changed, 165 insertions(+)
 create mode 100644 lib/poa/table/poa-table-columns.tsx

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

diff --git a/lib/poa/table/poa-table-columns.tsx b/lib/poa/table/poa-table-columns.tsx
new file mode 100644
index 00000000..b362e54c
--- /dev/null
+++ b/lib/poa/table/poa-table-columns.tsx
@@ -0,0 +1,165 @@
+"use client"
+
+import * as React from "react"
+import { type DataTableRowAction } from "@/types/table"
+import { type ColumnDef } from "@tanstack/react-table"
+import { InfoIcon, PenIcon } from "lucide-react"
+
+import { formatDate } from "@/lib/utils"
+import { Button } from "@/components/ui/button"
+import {
+  Tooltip,
+  TooltipContent,
+  TooltipProvider,
+  TooltipTrigger,
+} from "@/components/ui/tooltip"
+import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"
+import { POADetail } from "@/db/schema/contract"
+import { poaColumnsConfig } from "@/config/poaColumnsConfig"
+
+interface GetColumnsProps {
+  setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<POADetail> | null>>
+}
+
+/**
+ * tanstack table column definitions with nested headers
+ */
+export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<POADetail>[] {
+  // ----------------------------------------------------------------
+  // 1) actions column (buttons for item info)
+  // ----------------------------------------------------------------
+  const actionsColumn: ColumnDef<POADetail> = {
+    id: "actions",
+    enableHiding: false,
+    cell: function Cell({ row }) {
+      const hasSignature = row.original.hasSignature;
+      
+      return (
+        <div className="flex items-center space-x-1">
+          {/* Item Info Button */}
+          <TooltipProvider>
+            <Tooltip>
+              <TooltipTrigger asChild>
+                <Button
+                  variant="ghost"
+                  size="icon"
+                  onClick={() => setRowAction({ row, type: "items" })}
+                >
+                  <InfoIcon className="h-4 w-4" aria-hidden="true" />
+                </Button>
+              </TooltipTrigger>
+              <TooltipContent>
+                View Item Info
+              </TooltipContent>
+            </Tooltip>
+          </TooltipProvider>
+          
+          {/* Signature Request Button - only show if no signature exists */}
+          {!hasSignature && (
+            <TooltipProvider>
+              <Tooltip>
+                <TooltipTrigger asChild>
+                  <Button
+                    variant="ghost"
+                    size="icon"
+                    onClick={() => setRowAction({ row, type: "signature" })}
+                  >
+                    <PenIcon className="h-4 w-4" aria-hidden="true" />
+                  </Button>
+                </TooltipTrigger>
+                <TooltipContent>
+                  Request Electronic Signature
+                </TooltipContent>
+              </Tooltip>
+            </TooltipProvider>
+          )}
+        </div>
+      );
+    },
+    size: 80,
+  };
+
+  // ----------------------------------------------------------------
+  // 2) Regular columns grouped by group name
+  // ----------------------------------------------------------------
+  // 2-1) groupMap: { [groupName]: ColumnDef<POADetail>[] }
+  const groupMap: Record<string, ColumnDef<POADetail>[]> = {};
+
+  poaColumnsConfig.forEach((cfg) => {
+    // Use "_noGroup" if no group is specified
+    const groupName = cfg.group || "_noGroup";
+
+    if (!groupMap[groupName]) {
+      groupMap[groupName] = [];
+    }
+
+    // Child column definition
+    const childCol: ColumnDef<POADetail> = {
+      accessorKey: cfg.id,
+      enableResizing: true,
+      header: ({ column }) => (
+        <DataTableColumnHeaderSimple column={column} title={cfg.label} />
+      ),
+      meta: {
+        excelHeader: cfg.excelHeader,
+        group: cfg.group,
+        type: cfg.type,
+      },
+      cell: ({ cell }) => {
+        const value = cell.getValue();
+
+        if (cfg.type === "date") {
+          const dateVal = value as Date;
+          return (
+            <div className="text-sm">
+              {formatDate(dateVal)}
+            </div>
+          );
+        }
+        if (cfg.type === "number") {
+          const numVal = value as number;
+          return (
+            <div className="text-sm">
+              {numVal ? numVal.toLocaleString() : "-"}
+            </div>
+          );
+        }
+        return (
+          <div className="text-sm">
+            {value ?? "-"}
+          </div>
+        );
+      },
+    };
+
+    groupMap[groupName].push(childCol);
+  });
+
+  // ----------------------------------------------------------------
+  // 2-2) Create actual parent columns (groups) from the groupMap
+  // ----------------------------------------------------------------
+  const nestedColumns: ColumnDef<POADetail>[] = [];
+
+  // Order can be fixed by pre-defining group order or sorting
+  Object.entries(groupMap).forEach(([groupName, colDefs]) => {
+    if (groupName === "_noGroup") {
+      // No group → Add as top-level columns
+      nestedColumns.push(...colDefs);
+    } else {
+      // Parent column
+      nestedColumns.push({
+        id: groupName,
+        header: groupName,
+        columns: colDefs,
+      });
+    }
+  });
+
+  // ----------------------------------------------------------------
+  // 3) Final column array: nestedColumns + actionsColumn
+  // ----------------------------------------------------------------
+  return [
+    ...nestedColumns,
+    actionsColumn,
+  ];
+} 
\ No newline at end of file
-- 
cgit v1.2.3

