From e484964b1d78cedabbe182c789a8e4c9b53e29d3 Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Thu, 29 May 2025 05:12:36 +0000
Subject: (김준회) 기술영업 조선 RFQ 파일첨부 및 채팅 기능 구현 / menuConfig
 수정 (벤더 기술영업)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/techsales-rfq/table/rfq-table-column.tsx | 178 +++++++++------------------
 1 file changed, 59 insertions(+), 119 deletions(-)

(limited to 'lib/techsales-rfq/table/rfq-table-column.tsx')

diff --git a/lib/techsales-rfq/table/rfq-table-column.tsx b/lib/techsales-rfq/table/rfq-table-column.tsx
index caaa1c97..125e800b 100644
--- a/lib/techsales-rfq/table/rfq-table-column.tsx
+++ b/lib/techsales-rfq/table/rfq-table-column.tsx
@@ -6,10 +6,8 @@ import { formatDate, formatDateTime } from "@/lib/utils"
 import { Checkbox } from "@/components/ui/checkbox"
 import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"
 import { DataTableRowAction } from "@/types/table"
-import { Check, Pencil, X, Info } from "lucide-react"
+import { Info, Paperclip } from "lucide-react"
 import { Button } from "@/components/ui/button"
-import { toast } from "sonner"
-import { Input } from "@/components/ui/input"
 
 // 기본적인 RFQ 타입 정의 (rfq-table.tsx 파일과 일치해야 함)
 type TechSalesRfq = {
@@ -32,8 +30,8 @@ type TechSalesRfq = {
   updatedByName: string
   sentBy: number | null
   sentByName: string | null
-  projectSnapshot: any
-  seriesSnapshot: any
+  projectSnapshot: Record<string, unknown>
+  seriesSnapshot: Record<string, unknown>
   pspid: string
   projNm: string
   sector: string
@@ -42,28 +40,22 @@ type TechSalesRfq = {
   attachmentCount: number
   quotationCount: number
   // 나머지 필드는 사용할 때마다 추가
-  [key: string]: any
+  [key: string]: unknown
 }
 
+// 프로젝트 상세정보 타입 추가를 위한 확장
+// interface ExtendedDataTableRowAction<TData> extends DataTableRowAction<TData> {
+//   type: DataTableRowAction<TData>["type"] | "project-detail"
+// }
+
 interface GetColumnsProps {
   setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<TechSalesRfq> | null>>;
-  // 상태와 상태 설정 함수를 props로 받음
-  editingCell: EditingCellState | null;
-  setEditingCell: (state: EditingCellState | null) => void;
-  updateRemark: (rfqId: number, remark: string) => Promise<void>;
-}
-
-export interface EditingCellState {
-  rowId: string | number;
-  value: string;
+  openAttachmentsSheet: (rfqId: number) => void;
 }
 
-
 export function getColumns({
   setRowAction,
-  editingCell,
-  setEditingCell,
-  updateRemark,
+  openAttachmentsSheet,
 }: GetColumnsProps): ColumnDef<TechSalesRfq>[] {
   return [
     {
@@ -81,7 +73,7 @@ export function getColumns({
               // Then select just this row
               row.toggleSelected(true)
               // Trigger the same action that was in the "Select" button
-              setRowAction({ row, type: "select" })
+              setRowAction({ row, type: "select" as const })
             } else {
               // Just deselect this row
               row.toggleSelected(false)
@@ -142,7 +134,10 @@ export function getColumns({
       header: ({ column }) => (
         <DataTableColumnHeaderSimple column={column} title="자재명" />
       ),
-      cell: ({ row }) => <div>{row.getValue("itemName")}</div>,
+      cell: ({ row }) => {
+        const itemName = row.getValue("itemName");
+        return <div>{itemName || "자재명 없음"}</div>;
+      },
       meta: {
         excelHeader: "자재명"
       },
@@ -210,6 +205,48 @@ export function getColumns({
       enableResizing: true,
       size: 80,
     },
+    {
+      id: "attachments",
+      header: ({ column }) => (
+        <DataTableColumnHeaderSimple column={column} title="첨부파일" />
+      ),
+      cell: ({ row }) => {
+        const rfq = row.original
+        const attachmentCount = rfq.attachmentCount || 0
+
+        const handleClick = () => {
+          openAttachmentsSheet(rfq.id)
+        }
+
+        return (
+          <Button
+            variant="ghost"
+            size="sm"
+            className="relative h-8 w-8 p-0 group"
+            onClick={handleClick}
+            aria-label={
+              attachmentCount > 0 ? `View ${attachmentCount} attachments` : "Add attachments"
+            }
+          >
+            <Paperclip className="h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" />
+            {attachmentCount > 0 && (
+              <span className="pointer-events-none absolute -top-1 -right-1 inline-flex h-4 min-w-[1rem] items-center justify-center rounded-full bg-primary px-1 text-[0.625rem] font-medium leading-none text-primary-foreground">
+                {attachmentCount}
+              </span>
+            )}
+            <span className="sr-only">
+              {attachmentCount > 0 ? `${attachmentCount} 첨부파일` : "첨부파일 추가"}
+            </span>
+          </Button>
+        )
+      },
+      enableSorting: false,
+      enableResizing: true,
+      size: 80,
+      meta: {
+        excelHeader: "첨부파일"
+      },
+    },
     {
       accessorKey: "rfqSendDate",
       header: ({ column }) => (
@@ -283,103 +320,6 @@ export function getColumns({
       enableResizing: true,
       size: 160,
     },
-    // {
-    //   accessorKey: "remark",
-    //   header: ({ column }) => (
-    //     <DataTableColumnHeaderSimple column={column} title="비고" />
-    //   ),
-    //   cell: ({ row }) => {
-    //     const id = row.original.id;
-    //     const value = row.getValue("remark") as string;
-        
-    //     const isEditing = 
-    //       editingCell?.rowId === row.id &&
-    //       editingCell.value !== undefined;
-        
-    //     const startEditing = () => {
-    //       setEditingCell({
-    //         rowId: row.id,
-    //         value: value || ""
-    //       });
-    //     };
-        
-    //     const cancelEditing = () => {
-    //       setEditingCell(null);
-    //     };
-        
-    //     const saveChanges = async () => {
-    //       if (!editingCell) return;
-          
-    //       try {
-    //         await updateRemark(id, editingCell.value);
-    //         setEditingCell(null);
-    //       } catch (error) {
-    //         toast.error("비고 업데이트 중 오류가 발생했습니다.");
-    //         console.error("Error updating remark:", error);
-    //       }
-    //     };
-        
-    //     const handleKeyDown = (e: React.KeyboardEvent) => {
-    //       if (e.key === "Enter") {
-    //         saveChanges();
-    //       } else if (e.key === "Escape") {
-    //         cancelEditing();
-    //       }
-    //     };
-        
-    //     if (isEditing) {
-    //       return (
-    //         <div className="flex items-center gap-1">
-    //           <Input
-    //             value={editingCell?.value || ""}
-    //             onChange={(e) => setEditingCell({
-    //               rowId: row.id, 
-    //               value: e.target.value
-    //             })}
-    //             onKeyDown={handleKeyDown}
-    //             autoFocus
-    //             className="h-8 w-full"
-    //           />
-    //             <Button
-    //               variant="ghost"
-    //               size="icon"
-    //               onClick={saveChanges}
-    //             className="h-8 w-8"
-    //             >
-    //             <Check className="h-4 w-4" />
-    //             </Button>
-    //             <Button
-    //               variant="ghost"
-    //               size="icon"
-    //               onClick={cancelEditing}
-    //             className="h-8 w-8"
-    //             >
-    //             <X className="h-4 w-4" />
-    //             </Button>
-    //         </div>
-    //       );
-    //     }
-        
-    //     return (
-    //       <div className="flex items-center gap-1 group">
-    //         <span className="truncate">{value || ""}</span>
-    //         <Button
-    //           variant="ghost"
-    //           size="icon"
-    //           onClick={startEditing}
-    //           className="h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity"
-    //         >
-    //           <Pencil className="h-3 w-3" />
-    //         </Button>
-    //       </div>
-    //     );
-    //   },
-    //   meta: {
-    //     excelHeader: "비고"
-    //   },
-    //   enableResizing: true,
-    //   size: 200,
-    // },
     {
       id: "actions",
       header: ({ column }) => (
@@ -390,7 +330,7 @@ export function getColumns({
           <Button
             variant="ghost"
             size="sm"
-            onClick={() => setRowAction({ row, type: "project-detail" })}
+            onClick={() => setRowAction({ row, type: "view" as const })}
             className="h-8 px-2 gap-1"
           >
             <Info className="h-4 w-4" />
-- 
cgit v1.2.3

