// hooks/use-file-download.ts // 파일 다운로드 상태 관리 훅 import { useState, useCallback } from 'react'; import { downloadFile, type FileDownloadOptions, type FileDownloadResult } from '@/lib/file-download'; /** * 파일 다운로드 상태 */ interface FileDownloadState { isLoading: boolean; error: string | null; progress: number; lastResult: FileDownloadResult | null; } /** * 단일 파일 다운로드 훅 */ export const useFileDownload = () => { const [state, setState] = useState({ isLoading: false, error: null, progress: 0, lastResult: null, }); const download = useCallback(async ( filePath: string, fileName: string, options: FileDownloadOptions = {} ): Promise => { setState(prev => ({ ...prev, isLoading: true, error: null, progress: 0, })); const result = await downloadFile(filePath, fileName, { ...options, onProgress: (progress) => { setState(prev => ({ ...prev, progress })); if (options.onProgress) options.onProgress(progress); }, onError: (error) => { setState(prev => ({ ...prev, error, isLoading: false })); if (options.onError) options.onError(error); }, onSuccess: (fileName, fileSize) => { setState(prev => ({ ...prev, isLoading: false, error: null, progress: 100 })); if (options.onSuccess) options.onSuccess(fileName, fileSize); }, }); setState(prev => ({ ...prev, isLoading: false, lastResult: result, })); return result; }, []); const reset = useCallback(() => { setState({ isLoading: false, error: null, progress: 0, lastResult: null, }); }, []); return { ...state, download, reset, }; }; /** * 다중 파일 다운로드 훅 */ export const useMultiFileDownload = () => { const [downloads, setDownloads] = useState>(new Map()); const getFileState = useCallback((filePath: string): FileDownloadState => { return downloads.get(filePath) || { isLoading: false, error: null, progress: 0, lastResult: null, }; }, [downloads]); const isFileLoading = useCallback((filePath: string): boolean => { return downloads.get(filePath)?.isLoading || false; }, [downloads]); const getFileError = useCallback((filePath: string): string | null => { return downloads.get(filePath)?.error || null; }, [downloads]); const updateFileState = useCallback((filePath: string, updates: Partial) => { setDownloads(prev => { const newMap = new Map(prev); const currentState = newMap.get(filePath) || { isLoading: false, error: null, progress: 0, lastResult: null, }; newMap.set(filePath, { ...currentState, ...updates }); return newMap; }); }, []); const downloadFile = useCallback(async ( filePath: string, fileName: string, options: FileDownloadOptions = {} ): Promise => { updateFileState(filePath, { isLoading: true, error: null, progress: 0, }); const result = await downloadFile(filePath, fileName, { ...options, showToast: options.showToast ?? true, onProgress: (progress) => { updateFileState(filePath, { progress }); if (options.onProgress) options.onProgress(progress); }, onError: (error) => { updateFileState(filePath, { error, isLoading: false }); if (options.onError) options.onError(error); }, onSuccess: (fileName, fileSize) => { updateFileState(filePath, { isLoading: false, error: null, progress: 100 }); if (options.onSuccess) options.onSuccess(fileName, fileSize); }, }); updateFileState(filePath, { isLoading: false, lastResult: result, }); return result; }, [updateFileState]); const resetFile = useCallback((filePath: string) => { setDownloads(prev => { const newMap = new Map(prev); newMap.delete(filePath); return newMap; }); }, []); const resetAll = useCallback(() => { setDownloads(new Map()); }, []); return { downloads, getFileState, isFileLoading, getFileError, downloadFile, resetFile, resetAll, }; }; /** * 파일 다운로드 기본 설정 훅 */ export const useFileDownloadConfig = (defaultOptions: Partial = {}) => { const { download, ...state } = useFileDownload(); const downloadWithDefaults = useCallback(( filePath: string, fileName: string, options: FileDownloadOptions = {} ) => { return download(filePath, fileName, { ...defaultOptions, ...options }); }, [download, defaultOptions]); return { ...state, download: downloadWithDefaults, }; };