summaryrefslogtreecommitdiff
path: root/hooks/use-swp-documents.ts
diff options
context:
space:
mode:
Diffstat (limited to 'hooks/use-swp-documents.ts')
-rw-r--r--hooks/use-swp-documents.ts163
1 files changed, 163 insertions, 0 deletions
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<DocumentListItem[]>(
+ 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<DocumentDetail | null>(
+ 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]);
+}
+