ERP-node/frontend/hooks/useCompanyManagement.ts

308 lines
8.4 KiB
TypeScript
Raw Normal View History

2025-08-21 09:41:46 +09:00
import { useState, useCallback, useMemo, useEffect } from "react";
2025-09-05 14:52:10 +09:00
import {
Company,
CompanyFormData,
CompanyModalState,
CompanyDeleteState,
CompanySearchFilter,
AllDiskUsageInfo,
} from "@/types/company";
2025-08-21 09:41:46 +09:00
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,
});
2025-09-05 14:52:10 +09:00
// 디스크 사용량 상태
const [diskUsageInfo, setDiskUsageInfo] = useState<AllDiskUsageInfo | null>(null);
const [isDiskUsageLoading, setIsDiskUsageLoading] = useState(false);
2025-08-21 09:41:46 +09:00
// 회사 목록 로드
const loadCompanies = useCallback(async () => {
setIsLoading(true);
setError(null);
try {
// 실제 데이터베이스에서 회사 목록 조회
2025-08-21 09:41:46 +09:00
const searchParams = {
company_name: searchFilter.company_name,
status: searchFilter.status === "all" ? undefined : searchFilter.status,
};
// 더미 데이터 대신 실제 API 호출
2025-08-21 09:41:46 +09:00
const data = await companyAPI.getList(searchParams);
setCompanies(data);
console.log("✅ 실제 DB에서 회사 목록 조회 성공:", data.length, "개");
2025-08-21 09:41:46 +09:00
} catch (err) {
console.error("❌ 회사 목록 조회 실패:", err);
2025-08-21 09:41:46 +09:00
setError(err instanceof Error ? err.message : "회사 목록 조회에 실패했습니다.");
setCompanies([]);
} finally {
setIsLoading(false);
}
}, [searchFilter]);
2025-09-05 14:52:10 +09:00
// 디스크 사용량 로드
const loadDiskUsage = useCallback(async () => {
setIsDiskUsageLoading(true);
try {
const data = await companyAPI.getAllDiskUsage();
setDiskUsageInfo(data);
console.log("✅ 디스크 사용량 조회 성공:", data.summary);
} catch (err) {
console.error("❌ 디스크 사용량 조회 실패:", err);
// 디스크 사용량 조회 실패는 에러로 처리하지 않음 (선택적 기능)
} finally {
setIsDiskUsageLoading(false);
}
}, []);
2025-08-21 09:41:46 +09:00
// 초기 로드 및 검색 필터 변경 시 재로드
useEffect(() => {
loadCompanies();
2025-09-05 14:52:10 +09:00
loadDiskUsage(); // 디스크 사용량도 함께 로드
}, [loadCompanies, loadDiskUsage]);
// 디스크 사용량 정보가 포함된 회사 목록
const companiesWithDiskUsage = useMemo(() => {
if (!diskUsageInfo) return companies;
return companies.map((company) => {
const diskUsage = diskUsageInfo.companies.find((usage) => usage.companyCode === company.company_code);
return {
...company,
diskUsage: diskUsage
? {
fileCount: diskUsage.fileCount,
totalSize: diskUsage.totalSize,
totalSizeMB: diskUsage.totalSizeMB,
lastChecked: diskUsage.lastChecked,
}
: undefined,
};
});
}, [companies, diskUsageInfo]);
2025-08-21 09:41:46 +09:00
2025-09-05 14:52:10 +09:00
// 필터링된 회사 목록 (디스크 사용량 정보 포함)
2025-08-21 09:41:46 +09:00
const filteredCompanies = useMemo(() => {
2025-09-05 14:52:10 +09:00
return companiesWithDiskUsage;
}, [companiesWithDiskUsage]);
2025-08-21 09:41:46 +09:00
// 검색 필터 업데이트
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,
2025-09-05 14:52:10 +09:00
// 디스크 사용량 관련
diskUsageInfo,
isDiskUsageLoading,
loadDiskUsage,
2025-08-21 09:41:46 +09:00
// 모달 상태
modalState,
deleteState,
// 검색 기능
updateSearchFilter,
clearSearchFilter,
// 모달 제어
openCreateModal,
openEditModal,
closeModal,
updateFormData,
// 삭제 다이얼로그 제어
openDeleteDialog,
closeDeleteDialog,
// CRUD 작업
saveCompany,
deleteCompany,
loadCompanies, // 외부에서 수동으로 새로고침할 때 사용
// 에러 처리
clearError: () => setError(null),
};
};