import { useCallback, useEffect, useState } from 'react'; import { loadConfig } from '../utils'; import { useAlert } from '../context/AlertProvider'; import { alertTypes } from '../assets/data/types'; import * as APIConfigs from '../assets/data/apis' import { callAPI } from '../utils/apiService'; export const useCommonSearch = (configPath) => { const [config, setConfig] = useState(null); const [searchParams, setSearchParams] = useState({}); const [loading, setLoading] = useState(false); const [data, setData] = useState(null); const [configLoaded, setConfigLoaded] = useState(false); const { showToast } = useAlert(); const [apiEndpoint, setApiEndpoint] = useState(null); const [apiConfig, setApiConfig] = useState(null); // 설정 파일 로드 useEffect(() => { const fetchConfig = async () => { try { const configData = await loadConfig(configPath); setConfig(configData); // 초기 검색 파라미터 설정 if (configData.initialSearchParams) { setSearchParams(configData.initialSearchParams); } // API 엔드포인트 설정 가져오기 if (configData.apiInfo && configData.apiInfo.endpointName) { const endpointName = configData.apiInfo.endpointName; // API 설정 파일에서 엔드포인트 정보 찾기 for (const configKey in APIConfigs) { const apiConfigData = APIConfigs[configKey]; if (apiConfigData.endpoints && apiConfigData.endpoints[endpointName]) { setApiEndpoint(apiConfigData.endpoints[endpointName]); setApiConfig(apiConfigData); break; } } } setConfigLoaded(true); } catch (error) { console.error('Error loading search configuration:', error); } }; fetchConfig(); }, [configPath]); // 파라미터 값 변환 (날짜 등) const transformParams = useCallback((params) => { if (!config || !config.apiInfo || !config.apiInfo.paramTransforms) { return params; } const transformedParams = { ...params }; // 파라미터 변환 적용 config.apiInfo.paramTransforms.forEach(paramConfig => { if (paramConfig.param && paramConfig.transform) { const value = params[paramConfig.param]; if (value) { if (paramConfig.transform === 'toISOString') { transformedParams[paramConfig.param] = new Date(value).toISOString(); } // 필요시 다른 변환 로직 추가 } } }); return transformedParams; }, [config]); // 데이터 가져오기 const fetchData = useCallback(async (params) => { if (!apiEndpoint || !apiConfig) return; try { setLoading(true); const transformedParams = transformParams(params); // 페이지네이션 필드 옵션 const paginationOptions = { paginationType: config.paginationType }; if (config.apiInfo?.pageField) { paginationOptions.pageField = config.apiInfo.pageField; } if (config.apiInfo?.pageSizeField) { paginationOptions.pageSizeField = config.apiInfo.pageSizeField; } if (config.apiInfo?.orderField) { paginationOptions.orderField = config.apiInfo.orderField; } if (config.paginationType === 'dynamodb' && config.apiInfo?.lastPageKeyField) { paginationOptions.lastPageKeyField = config.apiInfo.lastPageKeyField; } // API 호출 const result = await callAPI( apiConfig, apiEndpoint, transformedParams, paginationOptions ); // 에러 처리 if (result.result && result.result.startsWith('ERROR')) { showToast(result.data.message, { type: alertTypes.error }); } // console.log(result.data); setData(result.data || result); return result.data || result; } catch (error) { console.error(`Error fetching data:`, error); throw error; } finally { setLoading(false); } }, [apiEndpoint, apiConfig, config, transformParams, showToast]); const initialLoad = useCallback((config) => { // loadOnMount가 undefined 또는 true인 경우 true 반환 return config?.apiInfo?.loadOnMount === undefined || config?.apiInfo?.loadOnMount === true; }, []); // 초기 데이터 로드 useEffect(() => { if (configLoaded && config && searchParams && apiEndpoint && config.apiInfo?.loadOnMount && initialLoad(config)) { fetchData(searchParams); } }, [configLoaded, config, searchParams, apiEndpoint, fetchData]); // 검색 파라미터 업데이트 const updateSearchParams = useCallback((newParams) => { setSearchParams(prev => ({ ...prev, ...newParams })); }, []); // 검색 처리 const handleSearch = useCallback(async (newParams = {}, executeSearch = true) => { if (!config) return null; const pageField = 'currentPage'; // 항상 내부적으로는 currentPage 사용 const updatedParams = { ...searchParams, ...newParams, [pageField]: newParams[pageField] || 1 // 새 검색 시 첫 페이지로 리셋 }; if (executeSearch && config.searchFields) { const requiredFields = config.searchFields.filter(field => field.required); for (const field of requiredFields) { if (!updatedParams[field.id] || updatedParams[field.id].trim() === '') { // 필수 필드가 비어있는 경우 showToast('SEARCH_REQUIRED_WARNING', { type: alertTypes.warning }); return null; } } } updateSearchParams(updatedParams); if (executeSearch) { return await fetchData(updatedParams); } return null; }, [searchParams, fetchData, config, updateSearchParams]); // 검색 초기화 const handleReset = useCallback(async () => { if (!config || !config.initialSearchParams) return null; setSearchParams(config.initialSearchParams); setData(null); // return await fetchData(config.initialSearchParams); }, [config, fetchData]); // 페이지 변경 const handlePageChange = useCallback(async (newPage) => { if (!config) return null; return await handleSearch({ currentPage: newPage }, true); }, [handleSearch, config]); // 페이지 크기 변경 const handlePageSizeChange = useCallback(async (newSize) => { if (!config) return null; return await handleSearch({ pageSize: newSize, currentPage: 1 }, true); }, [handleSearch, config]); // 정렬 방식 변경 const handleOrderByChange = useCallback(async (newOrder) => { if (!config) return null; return await handleSearch({ orderBy: newOrder }, true); }, [handleSearch, config]); return { config, searchParams, loading, data, handleSearch, handleReset, handlePageChange, handlePageSizeChange, handleOrderByChange, updateSearchParams, configLoaded }; }; export default useCommonSearch;