From 2ecdac866c19abea0b5389708fcdf5b3889c969a Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Wed, 29 Oct 2025 15:59:04 +0900 Subject: (김준회) SWP 파일 업로드 취소 기능 추가, 업로드 파일명 검증로직에서 파일명 비필수로 변경 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hooks/use-swp-documents.ts | 163 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 hooks/use-swp-documents.ts (limited to 'hooks') diff --git a/hooks/use-swp-documents.ts b/hooks/use-swp-documents.ts new file mode 100644 index 00000000..dca0ec9e --- /dev/null +++ b/hooks/use-swp-documents.ts @@ -0,0 +1,163 @@ +"use client"; + +import useSWR, { mutate } from "swr"; +import { + getDocumentList, + getDocumentDetail, + cancelStandbyFile, + downloadDocumentFile, + type DocumentListItem, + type DocumentDetail, + type DownloadFileResult, +} from "@/lib/swp/document-service"; + +// ============================================================================ +// SWR Hooks +// ============================================================================ + +/** + * 문서 목록 조회 Hook + * @param projNo 프로젝트 번호 + * @param vndrCd 벤더 코드 (선택) + */ +export function useDocumentList(projNo: string | null, vndrCd?: string) { + const key = projNo ? ["swp-documents", projNo, vndrCd] : null; + + return useSWR( + key, + async () => { + if (!projNo) return []; + return getDocumentList(projNo, vndrCd); + }, + { + revalidateOnFocus: false, // 포커스시 재검증 안함 + revalidateOnReconnect: true, // 재연결시 재검증 + dedupingInterval: 5000, // 5초간 중복 요청 방지 + } + ); +} + +/** + * 문서 상세 조회 Hook (Rev-Activity-File 트리) + * @param projNo 프로젝트 번호 + * @param docNo 문서 번호 + */ +export function useDocumentDetail( + projNo: string | null, + docNo: string | null +) { + const key = projNo && docNo ? ["swp-document-detail", projNo, docNo] : null; + + return useSWR( + key, + async () => { + if (!projNo || !docNo) throw new Error("projNo and docNo required"); + return getDocumentDetail(projNo, docNo); + }, + { + revalidateOnFocus: false, + revalidateOnReconnect: true, + dedupingInterval: 2000, // 2초간 중복 요청 방지 + shouldRetryOnError: false, + } + ); +} + +// ============================================================================ +// Mutation Helpers +// ============================================================================ + +/** + * 파일 취소 + */ +export async function useCancelFile( + boxSeq: string, + actvSeq: string, + userId: string, + options?: { + onSuccess?: () => void; + onError?: (error: Error) => void; + } +) { + try { + await cancelStandbyFile(boxSeq, actvSeq, userId); + + // 문서 상세 캐시 무효화 (재조회) + await mutate( + (key: unknown) => Array.isArray(key) && key[0] === "swp-document-detail", + undefined, + { revalidate: true } + ); + + // 문서 목록 캐시도 무효화 + await mutate( + (key: unknown) => Array.isArray(key) && key[0] === "swp-documents", + undefined, + { revalidate: true } + ); + + options?.onSuccess?.(); + } catch (error) { + options?.onError?.( + error instanceof Error ? error : new Error("파일 취소 실패") + ); + throw error; + } +} + +/** + * 파일 다운로드 + */ +export async function useDownloadFile( + projNo: string, + ownDocNo: string, + fileName: string, + options?: { + onSuccess?: () => void; + onError?: (error: string) => void; + } +) { + try { + const result: DownloadFileResult = await downloadDocumentFile( + projNo, + ownDocNo, + fileName + ); + + if (!result.success || !result.data) { + const errorMsg = result.error || "파일 다운로드 실패"; + options?.onError?.(errorMsg); + throw new Error(errorMsg); + } + + // Blob을 다운로드 + const blob = new Blob([Buffer.from(result.data)], { type: result.mimeType }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = result.fileName || fileName; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + + options?.onSuccess?.(); + } catch (error) { + const errorMsg = + error instanceof Error ? error.message : "파일 다운로드 실패"; + options?.onError?.(errorMsg); + throw error; + } +} + +/** + * 수동 새로고침 헬퍼 + */ +export function refreshDocumentList(projNo: string, vndrCd?: string) { + return mutate(["swp-documents", projNo, vndrCd]); +} + +export function refreshDocumentDetail(projNo: string, docNo: string) { + return mutate(["swp-document-detail", projNo, docNo]); +} + -- cgit v1.2.3