ERP-node/frontend/hooks/useCompanyManagement.ts

255 lines
6.9 KiB
TypeScript

import { useState, useCallback, useMemo, useEffect } from "react";
import { Company, CompanyFormData, CompanyModalState, CompanyDeleteState, CompanySearchFilter } from "@/types/company";
import { DEFAULT_COMPANY_FORM_DATA, COMPANY_STATUS } from "@/constants/company";
import { companyAPI } from "@/lib/api/company";
/**
* 회사 관리 비즈니스 로직을 담당하는 커스텀 훅
* CRUD 기능과 모달/다이얼로그 상태 관리
*/
export const useCompanyManagement = () => {
// 회사 목록 상태
const [companies, setCompanies] = useState<Company[]>([]);
// 검색 필터 상태
const [searchFilter, setSearchFilter] = useState<CompanySearchFilter>({});
// 로딩 및 에러 상태
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
// 모달 상태 (등록/수정)
const [modalState, setModalState] = useState<CompanyModalState>({
isOpen: false,
mode: "create",
selectedCompany: null,
formData: { ...DEFAULT_COMPANY_FORM_DATA },
});
// 삭제 다이얼로그 상태
const [deleteState, setDeleteState] = useState<CompanyDeleteState>({
isOpen: false,
targetCompany: null,
});
// 회사 목록 로드
const loadCompanies = useCallback(async () => {
setIsLoading(true);
setError(null);
try {
// 실제 데이터베이스에서 회사 목록 조회
const searchParams = {
company_name: searchFilter.company_name,
status: searchFilter.status === "all" ? undefined : searchFilter.status,
};
// 더미 데이터 대신 실제 API 호출
const data = await companyAPI.getList(searchParams);
setCompanies(data);
console.log("✅ 실제 DB에서 회사 목록 조회 성공:", data.length, "개");
} catch (err) {
console.error("❌ 회사 목록 조회 실패:", err);
setError(err instanceof Error ? err.message : "회사 목록 조회에 실패했습니다.");
setCompanies([]);
} finally {
setIsLoading(false);
}
}, [searchFilter]);
// 초기 로드 및 검색 필터 변경 시 재로드
useEffect(() => {
loadCompanies();
}, [loadCompanies]);
// 필터링된 회사 목록 (이제 서버에서 필터링되므로 그대로 반환)
const filteredCompanies = useMemo(() => {
return companies;
}, [companies]);
// 검색 필터 업데이트
const updateSearchFilter = useCallback((filter: Partial<CompanySearchFilter>) => {
setSearchFilter((prev) => ({ ...prev, ...filter }));
}, []);
// 검색 필터 초기화
const clearSearchFilter = useCallback(() => {
setSearchFilter({});
}, []);
// 모달 열기 - 새 회사 등록
const openCreateModal = useCallback(() => {
setModalState({
isOpen: true,
mode: "create",
selectedCompany: null,
formData: { ...DEFAULT_COMPANY_FORM_DATA },
});
}, []);
// 모달 열기 - 회사 수정
const openEditModal = useCallback((company: Company) => {
setModalState({
isOpen: true,
mode: "edit",
selectedCompany: company,
formData: {
company_name: company.company_name,
},
});
}, []);
// 모달 닫기
const closeModal = useCallback(() => {
setModalState((prev) => ({
...prev,
isOpen: false,
selectedCompany: null,
formData: { ...DEFAULT_COMPANY_FORM_DATA },
}));
}, []);
// 폼 데이터 변경
const updateFormData = useCallback((field: keyof CompanyFormData, value: string) => {
setModalState((prev) => ({
...prev,
formData: {
...prev.formData,
[field]: value,
},
}));
}, []);
// 회사 생성
const createCompany = useCallback(async () => {
if (!modalState.formData.company_name.trim()) {
setError("회사명을 입력해주세요.");
return false;
}
setIsLoading(true);
setError(null);
try {
await companyAPI.create(modalState.formData);
closeModal();
// 목록 다시 로드
await loadCompanies();
return true;
} catch (err) {
setError(err instanceof Error ? err.message : "회사 등록에 실패했습니다.");
return false;
} finally {
setIsLoading(false);
}
}, [modalState.formData, closeModal, loadCompanies]);
// 회사 수정
const updateCompany = useCallback(async () => {
if (!modalState.selectedCompany || !modalState.formData.company_name.trim()) {
setError("올바른 데이터를 입력해주세요.");
return false;
}
setIsLoading(true);
setError(null);
try {
await companyAPI.update(modalState.selectedCompany.company_code, {
company_name: modalState.formData.company_name,
status: modalState.selectedCompany.status,
});
closeModal();
// 목록 다시 로드
await loadCompanies();
return true;
} catch (err) {
setError(err instanceof Error ? err.message : "회사 수정에 실패했습니다.");
return false;
} finally {
setIsLoading(false);
}
}, [modalState.selectedCompany, modalState.formData, closeModal, loadCompanies]);
// 삭제 다이얼로그 열기
const openDeleteDialog = useCallback((company: Company) => {
setDeleteState({
isOpen: true,
targetCompany: company,
});
}, []);
// 삭제 다이얼로그 닫기
const closeDeleteDialog = useCallback(() => {
setDeleteState({
isOpen: false,
targetCompany: null,
});
}, []);
// 회사 삭제
const deleteCompany = useCallback(async () => {
if (!deleteState.targetCompany) return false;
setIsLoading(true);
setError(null);
try {
await companyAPI.delete(deleteState.targetCompany.company_code);
closeDeleteDialog();
// 목록 다시 로드
await loadCompanies();
return true;
} catch (err) {
setError(err instanceof Error ? err.message : "회사 삭제에 실패했습니다.");
return false;
} finally {
setIsLoading(false);
}
}, [deleteState.targetCompany, closeDeleteDialog, loadCompanies]);
// 폼 저장 (등록 또는 수정)
const saveCompany = useCallback(async () => {
if (modalState.mode === "create") {
return await createCompany();
} else {
return await updateCompany();
}
}, [modalState.mode, createCompany, updateCompany]);
return {
// 데이터
companies: filteredCompanies,
searchFilter,
isLoading,
error,
// 모달 상태
modalState,
deleteState,
// 검색 기능
updateSearchFilter,
clearSearchFilter,
// 모달 제어
openCreateModal,
openEditModal,
closeModal,
updateFormData,
// 삭제 다이얼로그 제어
openDeleteDialog,
closeDeleteDialog,
// CRUD 작업
saveCompany,
deleteCompany,
loadCompanies, // 외부에서 수동으로 새로고침할 때 사용
// 에러 처리
clearError: () => setError(null),
};
};