From d0d2eaa2de58a0c33e9a21604b126961403cd69e Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Wed, 14 May 2025 06:12:13 +0000
Subject: (최겸) 기술영업 조선, 해양Top, 해양 Hull 아이템 리스트 개발(CRUD,
 excel import/export/template)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../top/offshore-top-table-toolbar-actions.tsx     | 184 +++++++++++++++++++++
 1 file changed, 184 insertions(+)
 create mode 100644 lib/items-tech/table/top/offshore-top-table-toolbar-actions.tsx

(limited to 'lib/items-tech/table/top/offshore-top-table-toolbar-actions.tsx')

diff --git a/lib/items-tech/table/top/offshore-top-table-toolbar-actions.tsx b/lib/items-tech/table/top/offshore-top-table-toolbar-actions.tsx
new file mode 100644
index 00000000..324312aa
--- /dev/null
+++ b/lib/items-tech/table/top/offshore-top-table-toolbar-actions.tsx
@@ -0,0 +1,184 @@
+"use client"
+
+import * as React from "react"
+import { type Table } from "@tanstack/react-table"
+import { Download, FileDown } from "lucide-react"
+import * as ExcelJS from 'exceljs'
+import { saveAs } from "file-saver"
+
+import { Button } from "@/components/ui/button"
+import {
+  DropdownMenu,
+  DropdownMenuContent,
+  DropdownMenuItem,
+  DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu"
+
+import { DeleteItemsDialog } from "../delete-items-dialog"
+import { AddItemDialog } from "../add-items-dialog"
+import { exportTopItemTemplate } from "./item-excel-template"
+import { ImportItemButton } from "../import-excel-button"
+
+// 해양 TOP 아이템 타입 정의
+interface OffshoreTopItem {
+  id: number;
+  itemId: number;
+  workType: "TM" | "TS" | "TE" | "TP";
+  itemList1: string | null;
+  itemList2: string | null;
+  itemList3: string | null;
+  itemList4: string | null;
+  itemCode: string;
+  itemName: string;
+  description: string | null;
+  createdAt: Date;
+  updatedAt: Date;
+}
+
+interface OffshoreTopTableToolbarActionsProps {
+  table: Table<OffshoreTopItem>
+}
+
+export function OffshoreTopTableToolbarActions({ table }: OffshoreTopTableToolbarActionsProps) {
+  const [refreshKey, setRefreshKey] = React.useState(0)
+
+  // 가져오기 성공 후 테이블 갱신
+  const handleImportSuccess = () => {
+    setRefreshKey(prev => prev + 1)
+  }
+
+  // Excel 내보내기 함수
+  const exportTableToExcel = async (
+    table: Table<OffshoreTopItem>,
+    options: {
+      filename: string;
+      excludeColumns?: string[];
+      sheetName?: string;
+    }
+  ) => {
+    const { filename, excludeColumns = [], sheetName = "해양 TOP 아이템 목록" } = options;
+    
+    // 워크북 생성
+    const workbook = new ExcelJS.Workbook();
+    workbook.creator = 'Offshore Item Management System';
+    workbook.created = new Date();
+    
+    // 워크시트 생성
+    const worksheet = workbook.addWorksheet(sheetName);
+    
+    // 테이블 데이터 가져오기
+    const data = table.getFilteredRowModel().rows.map(row => row.original);
+    console.log("내보내기 데이터:", data);
+    
+    // 필요한 헤더 직접 정의 (필터링 문제 해결)
+    const headers = [
+      { key: 'itemCode', header: '아이템 코드' },
+      { key: 'itemName', header: '아이템 명' },
+      { key: 'description', header: '설명' },
+      { key: 'workType', header: '기능(공종)' },
+      { key: 'itemList1', header: '아이템 리스트 1' },
+      { key: 'itemList2', header: '아이템 리스트 2' },
+      { key: 'itemList3', header: '아이템 리스트 3' },
+      { key: 'itemList4', header: '아이템 리스트 4' }
+    ].filter(header => !excludeColumns.includes(header.key));
+    
+    console.log("내보내기 헤더:", headers);
+    // 컬럼 정의
+    worksheet.columns = headers.map(header => ({
+      header: header.header,
+      key: header.key,
+      width: 20 // 기본 너비
+    }));
+    
+    // 스타일 적용
+    const headerRow = worksheet.getRow(1);
+    headerRow.font = { bold: true };
+    headerRow.fill = {
+      type: 'pattern',
+      pattern: 'solid',
+      fgColor: { argb: 'FFE0E0E0' }
+    };
+    headerRow.alignment = { vertical: 'middle', horizontal: 'center' };
+    
+    // 데이터 행 추가
+    data.forEach(item => {
+      const row: Record<string, any> = {};
+      headers.forEach(header => {
+        row[header.key] = item[header.key as keyof OffshoreTopItem];
+      });
+      worksheet.addRow(row);
+    });
+    
+    // 전체 셀에 테두리 추가
+    worksheet.eachRow((row) => {
+      row.eachCell((cell) => {
+        cell.border = {
+          top: { style: 'thin' },
+          left: { style: 'thin' },
+          bottom: { style: 'thin' },
+          right: { style: 'thin' }
+        };
+      });
+    });
+    
+    try {
+      // 워크북을 Blob으로 변환
+      const buffer = await workbook.xlsx.writeBuffer();
+      const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
+      saveAs(blob, `${filename}.xlsx`);
+      return true;
+    } catch (error) {
+      console.error("Excel 내보내기 오류:", error);
+      return false;
+    }
+  }
+
+  return (
+    <div className="flex items-center gap-2">
+      {/* 선택된 로우가 있으면 삭제 다이얼로그 */}
+      {table.getFilteredSelectedRowModel().rows.length > 0 ? (
+        <DeleteItemsDialog
+          items={table
+            .getFilteredSelectedRowModel()
+            .rows.map((row) => row.original)}
+          onSuccess={() => table.toggleAllRowsSelected(false)}
+          itemType="offshoreTop"
+        />
+      ) : null}
+
+      {/* 새 아이템 추가 다이얼로그 */}
+      <AddItemDialog itemType="offshoreTop" />
+
+      {/* Import 버튼 */}
+      <ImportItemButton itemType="top" onSuccess={handleImportSuccess} />
+
+      {/* Export 드롭다운 메뉴 */}
+      <DropdownMenu>
+        <DropdownMenuTrigger asChild>
+          <Button variant="outline" size="sm" className="gap-2">
+            <Download className="size-4" aria-hidden="true" />
+            <span className="hidden sm:inline">Export</span>
+          </Button>
+        </DropdownMenuTrigger>
+        <DropdownMenuContent align="end">
+          <DropdownMenuItem
+            onClick={() =>
+              exportTableToExcel(table, {
+                filename: "offshore_top_items",
+                excludeColumns: ["select", "actions"],
+                sheetName: "해양 TOP 아이템 목록"
+              })
+            }
+          >
+            <FileDown className="mr-2 h-4 w-4" />
+            <span>현재 데이터 내보내기</span>
+          </DropdownMenuItem>
+          <DropdownMenuItem onClick={() => exportTopItemTemplate()}>
+            <FileDown className="mr-2 h-4 w-4" />
+            <span>템플릿 다운로드</span>
+          </DropdownMenuItem>
+        </DropdownMenuContent>
+      </DropdownMenu>
+    </div>
+  )
+} 
\ No newline at end of file
-- 
cgit v1.2.3

