321 lines
9.7 KiB
TypeScript
321 lines
9.7 KiB
TypeScript
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<CodeCategory[]>([]);
|
|
const [categoriesLoading, setCategoriesLoading] = useState(false);
|
|
const [categoriesError, setCategoriesError] = useState<string | null>(null);
|
|
const [totalCategories, setTotalCategories] = useState(0);
|
|
|
|
// 코드 관련 상태
|
|
const [codes, setCodes] = useState<CodeInfo[]>([]);
|
|
const [codesLoading, setCodesLoading] = useState(false);
|
|
const [codesError, setCodesError] = useState<string | null>(null);
|
|
|
|
// 선택된 카테고리
|
|
const [selectedCategoryCode, setSelectedCategoryCode] = useState<string>("");
|
|
|
|
/**
|
|
* 카테고리 목록 조회
|
|
*/
|
|
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,
|
|
};
|
|
}
|