diff options
Diffstat (limited to 'lib/swp')
| -rw-r--r-- | lib/swp/project-utils.ts | 47 | ||||
| -rw-r--r-- | lib/swp/table/swp-table-columns.tsx | 105 | ||||
| -rw-r--r-- | lib/swp/table/swp-table.tsx | 22 |
3 files changed, 133 insertions, 41 deletions
diff --git a/lib/swp/project-utils.ts b/lib/swp/project-utils.ts new file mode 100644 index 00000000..682c8da0 --- /dev/null +++ b/lib/swp/project-utils.ts @@ -0,0 +1,47 @@ +// lib/swp/project-utils.ts +import db from "@/db/db" +import { projects } from "@/db/schema" +import { eq } from "drizzle-orm" + +/** + * 프로젝트 코드(PROJ_NO)로 프로젝트 ID 조회 + * + * @param projectCode - 프로젝트 코드 (PROJ_NO) + * @returns 프로젝트 ID 또는 null + */ +export async function getProjectIdByCode(projectCode: string): Promise<number | null> { + try { + const [project] = await db + .select({ id: projects.id }) + .from(projects) + .where(eq(projects.code, projectCode)) + .limit(1) + + return project?.id || null + } catch (error) { + console.error(`❌ 프로젝트 ID 조회 실패 (코드: ${projectCode}):`, error) + return null + } +} + +/** + * 프로젝트 코드로 프로젝트 전체 정보 조회 + * + * @param projectCode - 프로젝트 코드 (PROJ_NO) + * @returns 프로젝트 정보 또는 null + */ +export async function getProjectByCode(projectCode: string) { + try { + const [project] = await db + .select() + .from(projects) + .where(eq(projects.code, projectCode)) + .limit(1) + + return project || null + } catch (error) { + console.error(`❌ 프로젝트 정보 조회 실패 (코드: ${projectCode}):`, error) + return null + } +} + diff --git a/lib/swp/table/swp-table-columns.tsx b/lib/swp/table/swp-table-columns.tsx index 5334bd8c..9fb85d2a 100644 --- a/lib/swp/table/swp-table-columns.tsx +++ b/lib/swp/table/swp-table-columns.tsx @@ -1,10 +1,12 @@ "use client"; +import React from "react"; import { ColumnDef } from "@tanstack/react-table"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; -import { Download } from "lucide-react"; +import { Download, Loader2 } from "lucide-react"; import type { DocumentListItem } from "@/lib/swp/document-service"; +import { toast } from "sonner"; export const swpDocumentColumns: ColumnDef<DocumentListItem>[] = [ { @@ -130,24 +132,87 @@ export const swpDocumentColumns: ColumnDef<DocumentListItem>[] = [ { id: "actions", header: "액션", - cell: ({ row }) => ( - <Button - variant="ghost" - size="sm" - onClick={(e) => { - e.stopPropagation(); // 행 클릭 이벤트 방지 - // 커버페이지 다운로드 핸들러는 부모 컴포넌트에서 제공 - const event = new CustomEvent('coverDownload', { - detail: { document: row.original } - }); - window.dispatchEvent(event); - }} - className="h-8 px-2" - > - <Download className="h-4 w-4 mr-1" /> - 커버페이지 - </Button> - ), - size: 120, + cell: function ActionCell({ row }) { + const [isDownloading, setIsDownloading] = React.useState(false); + + const handleDownloadCover = async (e: React.MouseEvent) => { + e.stopPropagation(); // 행 클릭 이벤트 방지 + + const docNumber = row.original.DOC_NO; + const projectCode = row.original.PROJ_NO; + + if (!docNumber || !projectCode) { + toast.error("문서 번호 또는 프로젝트 정보가 없습니다."); + return; + } + + setIsDownloading(true); + + try { + // 1. 프로젝트 코드로 프로젝트 ID 조회 + const projectIdResponse = await fetch( + `/api/projects/code-to-id?code=${encodeURIComponent(projectCode)}` + ); + + if (!projectIdResponse.ok) { + toast.error("프로젝트 정보를 찾을 수 없습니다."); + return; + } + + const { projectId } = await projectIdResponse.json(); + + // 2. 커버페이지 다운로드 API 호출 + const response = await fetch( + `/api/projects/${projectId}/cover?docNumber=${encodeURIComponent(docNumber)}` + ); + + if (!response.ok) { + const error = await response.json(); + throw new Error(error.message || "커버페이지 다운로드 실패"); + } + + // 3. 파일 다운로드 + const blob = await response.blob(); + const url = window.URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = `${docNumber}_cover.docx`; + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + + toast.success("커버페이지 다운로드가 시작되었습니다."); + + } catch (error) { + console.error("커버페이지 다운로드 오류:", error); + toast.error( + error instanceof Error + ? error.message + : "커버페이지 다운로드 중 오류가 발생했습니다." + ); + } finally { + setIsDownloading(false); + } + }; + + return ( + <Button + variant="ghost" + size="sm" + onClick={handleDownloadCover} + disabled={isDownloading} + className="h-8 w-8 p-0" + title="커버페이지 다운로드" + > + {isDownloading ? ( + <Loader2 className="h-4 w-4 animate-spin" /> + ) : ( + <Download className="h-4 w-4" /> + )} + </Button> + ); + }, + size: 80, }, ]; diff --git a/lib/swp/table/swp-table.tsx b/lib/swp/table/swp-table.tsx index 4d824f77..21a1c775 100644 --- a/lib/swp/table/swp-table.tsx +++ b/lib/swp/table/swp-table.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useState, useEffect } from "react"; +import React, { useState } from "react"; import { useReactTable, getCoreRowModel, @@ -17,15 +17,12 @@ import { import { swpDocumentColumns } from "./swp-table-columns"; import { SwpDocumentDetailDialog } from "./swp-document-detail-dialog"; import type { DocumentListItem } from "@/lib/swp/document-service"; -import { toast } from "sonner"; -import { quickDownload } from "@/lib/file-download"; interface SwpTableProps { documents: DocumentListItem[]; projNo: string; vendorCode: string; userId: string; - onCoverDownload?: (document: DocumentListItem) => void; } export function SwpTable({ @@ -33,7 +30,6 @@ export function SwpTable({ projNo, vendorCode, userId, - onCoverDownload, }: SwpTableProps) { const [dialogOpen, setDialogOpen] = useState(false); const [selectedDocument, setSelectedDocument] = useState<DocumentListItem | null>(null); @@ -50,22 +46,6 @@ export function SwpTable({ setDialogOpen(true); }; - // 커버페이지 다운로드 이벤트 리스너 - useEffect(() => { - const handleCoverDownload = (event: CustomEvent) => { - const { document } = event.detail; - if (onCoverDownload) { - onCoverDownload(document); - } - }; - - window.addEventListener('coverDownload', handleCoverDownload as EventListener); - - return () => { - window.removeEventListener('coverDownload', handleCoverDownload as EventListener); - }; - }, [onCoverDownload]); - return ( <div className="space-y-4"> {/* 테이블 */} |
