From cd0ce0cbe8af8719a6f542098ec78f2a5c1222ce Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Mon, 1 Dec 2025 10:28:05 +0000
Subject: (최겸) 구매 입찰 사전견적 개발(rfq-last)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/rfq-last/table/rfq-table-columns.tsx | 338 ++++++++++++++++++++++++++++++-
 1 file changed, 337 insertions(+), 1 deletion(-)

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

diff --git a/lib/rfq-last/table/rfq-table-columns.tsx b/lib/rfq-last/table/rfq-table-columns.tsx
index 62f14579..58c45aa0 100644
--- a/lib/rfq-last/table/rfq-table-columns.tsx
+++ b/lib/rfq-last/table/rfq-table-columns.tsx
@@ -24,7 +24,7 @@ type NextRouter = ReturnType<typeof useRouter>;
 
 interface GetColumnsProps {
   setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<RfqsLastView> | null>>;
-  rfqCategory?: "general" | "itb" | "rfq";
+  rfqCategory?: "general" | "itb" | "rfq" | "pre_bidding";
   router: NextRouter;
 }
 
@@ -755,6 +755,342 @@ export function getRfqColumns({
     ];
   }
 
+  // ═══════════════════════════════════════════════════════════════
+  // 사전견적(입찰) 컬럼 정의
+  // ═══════════════════════════════════════════════════════════════
+  if (rfqCategory === "pre_bidding") {
+    return [
+      // Checkbox
+      {
+        id: "select",
+        header: ({ table }) => (
+          <Checkbox
+            checked={table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && "indeterminate")}
+            onCheckedChange={(v) => table.toggleAllPageRowsSelected(!!v)}
+            aria-label="select all"
+            className="translate-y-0.5"
+          />
+        ),
+        cell: ({ row }) => (
+          <Checkbox
+            checked={row.getIsSelected()}
+            onCheckedChange={(v) => row.toggleSelected(!!v)}
+            aria-label="select row"
+            className="translate-y-0.5"
+          />
+        ),
+        size: 40,
+        enableSorting: false,
+        enableHiding: false,
+      },
+
+      // 견적 No.
+      {
+        accessorKey: "rfqCode",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적 No." />,
+        cell: ({ row }) => (
+          <span className="font-mono font-medium">{row.original.rfqCode}</span>
+        ),
+        size: 120,
+      },
+
+      // 입찰 No. (추가)
+      {
+        accessorKey: "biddingNumber",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="입찰 No." />,
+        cell: ({ row }) => (
+          <span className="font-mono font-medium">{row.original.biddingNumber || "-"}</span>
+        ),
+        size: 120,
+      },
+
+      // 상세 - 수정됨
+      {
+        id: "detail",
+        header: "상세",
+        cell: ({ row }) => (
+          <Button
+            variant="ghost"
+            size="icon"
+            className="h-8 w-8"
+            onClick={() => router.push(`/evcp/rfq-last/${row.original.id}`)}
+          >
+            <Eye className="h-4 w-4" />
+          </Button>
+        ),
+        size: 60,
+      },
+
+      // 견적상태
+      {
+        accessorKey: "status",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적상태" />,
+        cell: ({ row }) => (
+          <Badge variant={getStatusBadgeVariant(row.original.status)}>
+            {row.original.status}
+          </Badge>
+        ),
+        size: 120,
+      },
+
+      // 프로젝트 (프로젝트명)
+      {
+        accessorKey: "projectName",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="프로젝트 (프로젝트명)" />,
+        cell: ({ row }) => (
+          <div className="flex flex-col">
+            <span className="font-mono text-xs text-muted-foreground">
+              {row.original.projectCode}
+            </span>
+            <span className="max-w-[200px] truncate" title={row.original.projectName || ""}>
+              {row.original.projectName || "-"}
+            </span>
+          </div>
+        ),
+        size: 220,
+      },
+
+      // // 시리즈
+      // {
+      //   accessorKey: "series",
+      //   header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="시리즈" />,
+      //   cell: ({ row }) => {
+      //     const series = row.original.series;
+      //     if (!series) return "-";
+      //     const label = series === "SS" ? "시리즈 통합" : series === "II" ? "품목 통합" : series;
+      //     return <Badge variant="outline">{label}</Badge>;
+      //   },
+      //   size: 100,
+      // },
+
+      // // 선급
+      // {
+      //   accessorKey: "classNo",
+      //   header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="선급" />,
+      //   cell: ({ row }) => row.original.classNo || "-",
+      //   size: 80,
+      // },
+
+      // 견적명
+      {
+        accessorKey: "rfqTitle",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적명" />,
+        cell: ({ row }) => (
+          <div className="max-w-[200px] truncate" title={row.original.rfqTitle || ""}>
+            {row.original.rfqTitle || "-"}
+          </div>
+        ),
+        size: 200,
+      },
+
+      // 자재그룹 (자재그룹명)
+      {
+        accessorKey: "majorItemMaterialDescription",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="자재그룹 (자재그룹명)" />,
+        cell: ({ row }) => (
+          <div className="flex flex-col">
+            <span className="font-mono text-xs text-muted-foreground">
+              {row.original.majorItemMaterialCategory}
+            </span>
+            <span className="max-w-[150px] truncate" title={row.original.majorItemMaterialDescription || ""}>
+              {row.original.majorItemMaterialDescription || "-"}
+            </span>
+          </div>
+        ),
+        size: 180,
+      },
+
+      // 자재코드
+      {
+        accessorKey: "itemCode",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="자재코드" />,
+        cell: ({ row }) => (
+          <span className="font-mono text-sm">{row.original.itemCode || "-"}</span>
+        ),
+        size: 100,
+      },
+      // 자재명
+      {
+        accessorKey: "itemName",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="자재명" />,
+        cell: ({ row }) => (
+          <span className="font-mono text-sm">{row.original.itemName || "-"}</span>
+        ),
+        size: 100,
+      },
+
+      // 견적 자료
+      {
+        id: "rfqDocument",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적 자료" />,
+        cell: ({ row }) => (
+          <Button 
+            variant="ghost" 
+            size="sm"
+            onClick={() => setRowAction({ row, type: "attachment" })}
+          >
+            <FileText className="h-4 w-4" />
+          </Button>
+        ),
+        size: 80,
+      },
+
+      // 견적품목수
+      {
+        accessorKey: "prItemsCount",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적품목수" />,
+        cell: ({ row }) => (
+          <Button
+            variant="ghost"
+            size="sm"
+            className="font-mono text-sm p-1 h-auto"
+            onClick={() => setRowAction({ row, type: "items" })}
+          >
+            {row.original.prItemsCount || 0}
+          </Button>
+        ),
+        size: 90,
+      },
+
+      // 견적생성일
+      {
+        accessorKey: "createdAt",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적생성일" />,
+        cell: ({ row }) => {
+          const date = row.original.createdAt;
+          return date ? format(new Date(date), "yyyy-MM-dd") : "-";
+        },
+        size: 100,
+      },
+
+      // 견적발송일
+      {
+        accessorKey: "rfqSendDate",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적발송일" />,
+        cell: ({ row }) => {
+          const date = row.original.rfqSendDate;
+          return date ? format(new Date(date), "yyyy-MM-dd") : "-";
+        },
+        size: 100,
+      },
+
+      // 견적마감일
+      {
+        accessorKey: "dueDate",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="견적마감일" />,
+        cell: ({ row }) => {
+          const date = row.original.dueDate;
+          if (!date) return "-";
+          
+          const now = new Date();
+          const dueDate = new Date(date);
+          const daysLeft = differenceInDays(dueDate, now);
+          
+          // 상태별 스타일과 아이콘 설정
+          let statusIcon;
+          let statusText;
+          let statusClass;
+          
+          if (daysLeft < 0) {
+            const daysOverdue = Math.abs(daysLeft);
+            statusIcon = <XCircle className="h-4 w-4" />;
+            statusText = `${daysOverdue}일 지남`;
+            statusClass = "text-red-600";
+          } else if (daysLeft === 0) {
+            statusIcon = <AlertTriangle className="h-4 w-4" />;
+            statusText = "오늘 마감";
+            statusClass = "text-orange-600";
+          } else if (daysLeft <= 3) {
+            statusIcon = <AlertCircle className="h-4 w-4" />;
+            statusText = `${daysLeft}일 남음`;
+            statusClass = "text-amber-600";
+          } else if (daysLeft <= 7) {
+            statusIcon = <Clock className="h-4 w-4" />;
+            statusText = `${daysLeft}일 남음`;
+            statusClass = "text-blue-600";
+          } else {
+            statusIcon = <CheckCircle className="h-4 w-4" />;
+            statusText = `${daysLeft}일 남음`;
+            statusClass = "text-green-600";
+          }
+          
+          return (
+            <div className="flex flex-col gap-1">
+              <span className="text-sm text-muted-foreground">
+                {format(dueDate, "yyyy-MM-dd")}
+              </span>
+              <div className={`flex items-center gap-1 ${statusClass}`}>
+                {statusIcon}
+                <span className="text-xs font-medium">{statusText}</span>
+              </div>
+            </div>
+          );
+        },
+        size: 120,
+      },
+
+      // 계약기간 (추가)
+      {
+        id: "contractPeriod",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="계약기간" />,
+        cell: ({ row }) => {
+          const start = row.original.contractStartDate;
+          const end = row.original.contractEndDate;
+          
+          if (!start && !end) return "-";
+          
+          return (
+            <div className="flex flex-col text-xs">
+              <span>{start ? format(new Date(start), "yyyy-MM-dd") : "미정"}</span>
+              <span className="text-muted-foreground">~</span>
+              <span>{end ? format(new Date(end), "yyyy-MM-dd") : "미정"}</span>
+            </div>
+          );
+        },
+        size: 120,
+      },
+
+      // 구매담당자
+      {
+        accessorKey: "picUserName",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="구매담당자" />,
+        cell: ({ row }) => {
+          const name = row.original.picUserName || row.original.picName || "-";
+          const picCode = row.original.picCode || "";
+          return name === "-" ? "-" : `${name}(${picCode})`;
+        },
+        size: 100,
+      },
+
+      // 최종수정일
+      {
+        accessorKey: "updatedAt",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="최종수정일" />,
+        cell: ({ row }) => {
+          const date = row.original.updatedAt;
+          return date ? format(new Date(date), "yyyy-MM-dd HH:mm") : "-";
+        },
+        size: 120,
+      },
+
+      // 최종수정자
+      {
+        accessorKey: "updatedByUserName",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="최종수정자" />,
+        cell: ({ row }) => row.original.updatedByUserName || "-",
+        size: 100,
+      },
+
+      // 비고
+      {
+        accessorKey: "remark",
+        header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="비고" />,
+        cell: ({ row }) => row.original.remark || "-",
+        size: 150,
+      },
+    ];
+  }
+
   // ═══════════════════════════════════════════════════════════════
   // 일반견적 컬럼 정의
   // ═══════════════════════════════════════════════════════════════
-- 
cgit v1.2.3

