Files
operationSystem-front/src/hooks/useCommonSearch.js
bcjang fa290b64ec api 공통 모듈생성
search, api 공통 모듈 생성
공통모듈 화면 별 반영
2025-05-01 07:04:14 +09:00

227 lines
6.4 KiB
JavaScript

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;