import { useState, useEffect, useCallback } from "react"; import { commonCodeApi } from "@/lib/api/commonCode"; import { CodeCategory, CodeInfo, CreateCategoryRequest, UpdateCategoryRequest, CreateCodeRequest, UpdateCodeRequest, GetCategoriesQuery, GetCodesQuery, } from "@/types/commonCode"; /** * 공통코드 관리를 위한 커스텀 훅 */ export function useCommonCode() { // 카테고리 관련 상태 const [categories, setCategories] = useState([]); const [categoriesLoading, setCategoriesLoading] = useState(false); const [categoriesError, setCategoriesError] = useState(null); const [totalCategories, setTotalCategories] = useState(0); // 코드 관련 상태 const [codes, setCodes] = useState([]); const [codesLoading, setCodesLoading] = useState(false); const [codesError, setCodesError] = useState(null); // 선택된 카테고리 const [selectedCategoryCode, setSelectedCategoryCode] = useState(""); /** * 카테고리 목록 조회 */ const fetchCategories = useCallback(async (params?: GetCategoriesQuery) => { setCategoriesLoading(true); setCategoriesError(null); try { const response = await commonCodeApi.categories.getList(params); if (response.success) { setCategories(response.data || []); setTotalCategories(response.total || 0); setCategoriesError(null); // 에러 상태 초기화 } else { throw new Error(response.message || "카테고리 조회에 실패했습니다."); } } catch (error) { const errorMessage = error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다."; setCategoriesError(errorMessage); console.error("카테고리 조회 오류:", error); } finally { setCategoriesLoading(false); } }, []); /** * 코드 목록 조회 */ const fetchCodes = useCallback(async (categoryCode: string, params?: GetCodesQuery) => { if (!categoryCode) { setCodes([]); return; } setCodesLoading(true); setCodesError(null); try { const response = await commonCodeApi.codes.getList(categoryCode, params); if (response.success && response.data) { setCodes(response.data); } else { throw new Error(response.message || "코드 조회에 실패했습니다."); } } catch (error) { const errorMessage = error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다."; setCodesError(errorMessage); console.error("코드 조회 오류:", error); } finally { setCodesLoading(false); } }, []); /** * 카테고리 생성 */ const createCategory = useCallback( async (data: CreateCategoryRequest) => { try { const response = await commonCodeApi.categories.create(data); if (response.success) { // 🔥 즉시 UI 업데이트: 새로운 카테고리를 현재 목록에 추가 const newCategory = response.data; setCategories((prevCategories) => [...prevCategories, newCategory]); // 🔄 동시에 서버에서 최신 데이터 가져오기 (백그라운드) fetchCategories(); return response; } else { throw new Error(response.message || "카테고리 생성에 실패했습니다."); } } catch (error) { console.error("카테고리 생성 오류:", error); throw error; } }, [fetchCategories], ); /** * 카테고리 수정 */ const updateCategory = useCallback( async (categoryCode: string, data: UpdateCategoryRequest) => { try { const response = await commonCodeApi.categories.update(categoryCode, data); if (response.success) { // 🔥 즉시 UI 업데이트: 수정된 카테고리를 현재 목록에서 업데이트 const updatedCategory = response.data; setCategories((prevCategories) => prevCategories.map((category) => (category.category_code === categoryCode ? updatedCategory : category)), ); // 🔄 동시에 서버에서 최신 데이터 가져오기 (백그라운드) fetchCategories(); return response; } else { throw new Error(response.message || "카테고리 수정에 실패했습니다."); } } catch (error) { console.error("카테고리 수정 오류:", error); throw error; } }, [fetchCategories], ); /** * 카테고리 삭제 */ const deleteCategory = useCallback( async (categoryCode: string) => { try { const response = await commonCodeApi.categories.delete(categoryCode); if (response.success) { // 🔥 즉시 UI 업데이트: 삭제된 카테고리를 현재 목록에서 제거 setCategories((prevCategories) => prevCategories.filter((category) => category.category_code !== categoryCode), ); // 선택된 카테고리가 삭제된 경우 선택 해제 if (selectedCategoryCode === categoryCode) { setSelectedCategoryCode(""); // 선택 해제 setCodes([]); // 코드 목록 초기화 } // 🔄 동시에 서버에서 최신 데이터 가져오기 (백그라운드) fetchCategories(); return response; } else { throw new Error(response.message || "카테고리 삭제에 실패했습니다."); } } catch (error) { console.error("카테고리 삭제 오류:", error); throw error; } }, [fetchCategories, selectedCategoryCode], ); /** * 코드 생성 */ const createCode = useCallback( async (categoryCode: string, data: CreateCodeRequest) => { try { const response = await commonCodeApi.codes.create(categoryCode, data); if (response.success) { // 🔥 즉시 UI 업데이트: 새로운 코드를 현재 목록에 추가 const newCode = response.data; setCodes((prevCodes) => [...prevCodes, newCode]); // 🔄 동시에 서버에서 최신 데이터 가져오기 (백그라운드) fetchCodes(categoryCode); return response; } else { throw new Error(response.message || "코드 생성에 실패했습니다."); } } catch (error) { console.error("코드 생성 오류:", error); throw error; } }, [fetchCodes], ); /** * 코드 수정 */ const updateCode = useCallback( async (categoryCode: string, codeValue: string, data: UpdateCodeRequest) => { try { const response = await commonCodeApi.codes.update(categoryCode, codeValue, data); if (response.success) { // 🔥 즉시 UI 업데이트: 수정된 코드를 현재 목록에서 업데이트 const updatedCode = response.data; setCodes((prevCodes) => prevCodes.map((code) => (code.code_value === codeValue ? updatedCode : code))); // 🔄 동시에 서버에서 최신 데이터 가져오기 (백그라운드) fetchCodes(categoryCode); return response; } else { throw new Error(response.message || "코드 수정에 실패했습니다."); } } catch (error) { console.error("코드 수정 오류:", error); throw error; } }, [fetchCodes], ); /** * 코드 삭제 */ const deleteCode = useCallback( async (categoryCode: string, codeValue: string) => { try { const response = await commonCodeApi.codes.delete(categoryCode, codeValue); if (response.success) { // 🔥 즉시 UI 업데이트: 삭제된 코드를 현재 목록에서 제거 setCodes((prevCodes) => prevCodes.filter((code) => code.code_value !== codeValue)); // 🔄 동시에 서버에서 최신 데이터 가져오기 (백그라운드) fetchCodes(categoryCode); return response; } else { throw new Error(response.message || "코드 삭제에 실패했습니다."); } } catch (error) { console.error("코드 삭제 오류:", error); throw error; } }, [fetchCodes], ); const reorderCodes = useCallback( async (categoryCode: string, codes: Array<{ codeValue: string; sortOrder: number }>) => { try { const response = await commonCodeApi.codes.reorder(categoryCode, { codes }); if (response.success) { console.log("✅ 코드 순서 변경 성공"); } else { throw new Error(response.message || "코드 순서 변경에 실패했습니다."); } } catch (error) { const errorMessage = error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다."; console.error("코드 순서 변경 오류:", error); throw error; } }, [], ); /** * 초기 데이터 로드 */ useEffect(() => { fetchCategories(); }, [fetchCategories]); /** * 선택된 카테고리 변경 시 코드 목록 로드 */ useEffect(() => { if (selectedCategoryCode) { fetchCodes(selectedCategoryCode); } else { setCodes([]); } }, [selectedCategoryCode, fetchCodes]); return { // 카테고리 관련 categories, categoriesLoading, categoriesError, totalCategories, fetchCategories, createCategory, updateCategory, deleteCategory, // 코드 관련 codes, setCodes, codesLoading, codesError, fetchCodes, createCode, updateCode, deleteCode, reorderCodes, // 선택된 카테고리 selectedCategoryCode, setSelectedCategoryCode, }; }