summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-11-03 17:28:06 +0900
committerjoonhoekim <26rote@gmail.com>2025-11-03 17:28:06 +0900
commita9c038e51f1cf508165e9d196ffe332f6ac54d74 (patch)
tree406d7083621902eeaff4cce6c1c306445f57e4e9
parentdf5a6201bdf8ff9edfc6429b918cf2fd2b245684 (diff)
(김준회) SWP: 커버페이지 다운로드 버튼 추가 (문서별)
-rw-r--r--app/[lng]/partners/(partners)/swp-document-upload/vendor-document-page.tsx29
-rw-r--r--lib/swp/table/swp-table-columns.tsx25
-rw-r--r--lib/swp/table/swp-table.tsx22
3 files changed, 75 insertions, 1 deletions
diff --git a/app/[lng]/partners/(partners)/swp-document-upload/vendor-document-page.tsx b/app/[lng]/partners/(partners)/swp-document-upload/vendor-document-page.tsx
index dc6fbe7c..34ad562f 100644
--- a/app/[lng]/partners/(partners)/swp-document-upload/vendor-document-page.tsx
+++ b/app/[lng]/partners/(partners)/swp-document-upload/vendor-document-page.tsx
@@ -70,6 +70,34 @@ export default function VendorDocumentPage({ searchParams }: VendorDocumentPageP
noKeyboard: true,
});
+ // 커버페이지 다운로드 핸들러
+ const handleCoverDownload = useCallback(async (document: DocumentListItem) => {
+ try {
+ toast.info("커버 페이지를 다운로드합니다...");
+
+ const res = await fetch(`/api/projects/${document.PROJ_NO}/cover`, {
+ method: "GET"
+ });
+
+ if (!res.ok) {
+ const error = await res.json();
+ throw new Error(error.message || "커버 페이지를 가져올 수 없습니다");
+ }
+
+ const { fileUrl, fileName } = await res.json();
+
+ // quickDownload 사용
+ const quickDownload = (await import("@/lib/file-download")).quickDownload;
+ quickDownload(fileUrl, fileName || `${document.PROJ_NO}_cover.docx`);
+
+ toast.success("커버 페이지 다운로드를 시작했습니다.");
+
+ } catch (e) {
+ toast.error(e instanceof Error ? e.message : "커버 페이지 다운로드에 실패했습니다.");
+ console.error(e);
+ }
+ }, []);
+
const loadInitialData = useCallback(async () => {
try {
setIsLoading(true);
@@ -275,6 +303,7 @@ export default function VendorDocumentPage({ searchParams }: VendorDocumentPageP
projNo={projNo}
vendorCode={vendorInfo?.vendorCode || ""}
userId={String(vendorInfo?.vendorId || "")}
+ onCoverDownload={handleCoverDownload}
/>
</CardContent>
</Card>
diff --git a/lib/swp/table/swp-table-columns.tsx b/lib/swp/table/swp-table-columns.tsx
index 48b2c90a..5334bd8c 100644
--- a/lib/swp/table/swp-table-columns.tsx
+++ b/lib/swp/table/swp-table-columns.tsx
@@ -2,6 +2,8 @@
import { ColumnDef } from "@tanstack/react-table";
import { Badge } from "@/components/ui/badge";
+import { Button } from "@/components/ui/button";
+import { Download } from "lucide-react";
import type { DocumentListItem } from "@/lib/swp/document-service";
export const swpDocumentColumns: ColumnDef<DocumentListItem>[] = [
@@ -125,4 +127,27 @@ export const swpDocumentColumns: ColumnDef<DocumentListItem>[] = [
),
size: 100,
},
+ {
+ 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,
+ },
];
diff --git a/lib/swp/table/swp-table.tsx b/lib/swp/table/swp-table.tsx
index 21a1c775..4d824f77 100644
--- a/lib/swp/table/swp-table.tsx
+++ b/lib/swp/table/swp-table.tsx
@@ -1,6 +1,6 @@
"use client";
-import React, { useState } from "react";
+import React, { useState, useEffect } from "react";
import {
useReactTable,
getCoreRowModel,
@@ -17,12 +17,15 @@ 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({
@@ -30,6 +33,7 @@ export function SwpTable({
projNo,
vendorCode,
userId,
+ onCoverDownload,
}: SwpTableProps) {
const [dialogOpen, setDialogOpen] = useState(false);
const [selectedDocument, setSelectedDocument] = useState<DocumentListItem | null>(null);
@@ -46,6 +50,22 @@ 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">
{/* 테이블 */}