'use client'; /** * CEO Dashboard API 연동 Hook * * 각 섹션별 API 호출 및 데이터 변환 담당 * 참조 패턴: useClientList.ts */ import { useState, useCallback, useEffect } from 'react'; import type { DailyReportApiResponse, ReceivablesApiResponse, BadDebtApiResponse, ExpectedExpenseApiResponse, CardTransactionApiResponse, } from '@/lib/api/dashboard/types'; import { transformDailyReportResponse, transformReceivableResponse, transformDebtCollectionResponse, transformMonthlyExpenseResponse, transformCardManagementResponse, } from '@/lib/api/dashboard/transformers'; import type { DailyReportData, ReceivableData, DebtCollectionData, MonthlyExpenseData, CardManagementData, } from '@/components/business/CEODashboard/types'; // ============================================ // 공통 fetch 유틸리티 // ============================================ async function fetchApi(endpoint: string): Promise { const response = await fetch(`/api/proxy/${endpoint}`); if (!response.ok) { throw new Error(`API 오류: ${response.status}`); } const result = await response.json(); if (!result.success) { throw new Error(result.message || '데이터 조회 실패'); } return result.data; } // ============================================ // 1. DailyReport Hook // ============================================ export function useDailyReport() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchData = useCallback(async () => { try { setLoading(true); setError(null); const apiData = await fetchApi('daily-report/summary'); const transformed = transformDailyReportResponse(apiData); setData(transformed); } catch (err) { const errorMessage = err instanceof Error ? err.message : '데이터 로딩 실패'; setError(errorMessage); console.error('DailyReport API Error:', err); } finally { setLoading(false); } }, []); useEffect(() => { fetchData(); }, [fetchData]); return { data, loading, error, refetch: fetchData }; } // ============================================ // 2. Receivable Hook // ============================================ export function useReceivable() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchData = useCallback(async () => { try { setLoading(true); setError(null); const apiData = await fetchApi('receivables/summary'); const transformed = transformReceivableResponse(apiData); setData(transformed); } catch (err) { const errorMessage = err instanceof Error ? err.message : '데이터 로딩 실패'; setError(errorMessage); console.error('Receivable API Error:', err); } finally { setLoading(false); } }, []); useEffect(() => { fetchData(); }, [fetchData]); return { data, loading, error, refetch: fetchData }; } // ============================================ // 3. DebtCollection Hook // ============================================ export function useDebtCollection() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchData = useCallback(async () => { try { setLoading(true); setError(null); const apiData = await fetchApi('bad-debts/summary'); const transformed = transformDebtCollectionResponse(apiData); setData(transformed); } catch (err) { const errorMessage = err instanceof Error ? err.message : '데이터 로딩 실패'; setError(errorMessage); console.error('DebtCollection API Error:', err); } finally { setLoading(false); } }, []); useEffect(() => { fetchData(); }, [fetchData]); return { data, loading, error, refetch: fetchData }; } // ============================================ // 4. MonthlyExpense Hook // ============================================ export function useMonthlyExpense() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchData = useCallback(async () => { try { setLoading(true); setError(null); const apiData = await fetchApi('expected-expenses/summary'); const transformed = transformMonthlyExpenseResponse(apiData); setData(transformed); } catch (err) { const errorMessage = err instanceof Error ? err.message : '데이터 로딩 실패'; setError(errorMessage); console.error('MonthlyExpense API Error:', err); } finally { setLoading(false); } }, []); useEffect(() => { fetchData(); }, [fetchData]); return { data, loading, error, refetch: fetchData }; } // ============================================ // 5. CardManagement Hook // ============================================ export function useCardManagement(fallbackData?: CardManagementData) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchData = useCallback(async () => { try { setLoading(true); setError(null); const apiData = await fetchApi('card-transactions/summary'); const transformed = transformCardManagementResponse(apiData, fallbackData); setData(transformed); } catch (err) { const errorMessage = err instanceof Error ? err.message : '데이터 로딩 실패'; setError(errorMessage); console.error('CardManagement API Error:', err); } finally { setLoading(false); } }, [fallbackData]); useEffect(() => { fetchData(); }, [fetchData]); return { data, loading, error, refetch: fetchData }; } // ============================================ // 통합 Dashboard Hook (선택적 사용) // ============================================ export interface UseCEODashboardOptions { /** DailyReport 섹션 활성화 */ dailyReport?: boolean; /** Receivable 섹션 활성화 */ receivable?: boolean; /** DebtCollection 섹션 활성화 */ debtCollection?: boolean; /** MonthlyExpense 섹션 활성화 */ monthlyExpense?: boolean; /** CardManagement 섹션 활성화 */ cardManagement?: boolean; /** CardManagement fallback 데이터 */ cardManagementFallback?: CardManagementData; } export interface CEODashboardState { dailyReport: { data: DailyReportData | null; loading: boolean; error: string | null; }; receivable: { data: ReceivableData | null; loading: boolean; error: string | null; }; debtCollection: { data: DebtCollectionData | null; loading: boolean; error: string | null; }; monthlyExpense: { data: MonthlyExpenseData | null; loading: boolean; error: string | null; }; cardManagement: { data: CardManagementData | null; loading: boolean; error: string | null; }; refetchAll: () => void; } /** * 통합 CEO Dashboard Hook * 여러 섹션의 API를 병렬로 호출하여 성능 최적화 */ export function useCEODashboard(options: UseCEODashboardOptions = {}): CEODashboardState { const { dailyReport: enableDailyReport = true, receivable: enableReceivable = true, debtCollection: enableDebtCollection = true, monthlyExpense: enableMonthlyExpense = true, cardManagement: enableCardManagement = true, cardManagementFallback, } = options; // 각 섹션별 상태 const [dailyReportData, setDailyReportData] = useState(null); const [dailyReportLoading, setDailyReportLoading] = useState(enableDailyReport); const [dailyReportError, setDailyReportError] = useState(null); const [receivableData, setReceivableData] = useState(null); const [receivableLoading, setReceivableLoading] = useState(enableReceivable); const [receivableError, setReceivableError] = useState(null); const [debtCollectionData, setDebtCollectionData] = useState(null); const [debtCollectionLoading, setDebtCollectionLoading] = useState(enableDebtCollection); const [debtCollectionError, setDebtCollectionError] = useState(null); const [monthlyExpenseData, setMonthlyExpenseData] = useState(null); const [monthlyExpenseLoading, setMonthlyExpenseLoading] = useState(enableMonthlyExpense); const [monthlyExpenseError, setMonthlyExpenseError] = useState(null); const [cardManagementData, setCardManagementData] = useState(null); const [cardManagementLoading, setCardManagementLoading] = useState(enableCardManagement); const [cardManagementError, setCardManagementError] = useState(null); // 개별 fetch 함수들 const fetchDailyReport = useCallback(async () => { if (!enableDailyReport) return; try { setDailyReportLoading(true); setDailyReportError(null); const apiData = await fetchApi('daily-report/summary'); setDailyReportData(transformDailyReportResponse(apiData)); } catch (err) { setDailyReportError(err instanceof Error ? err.message : '데이터 로딩 실패'); } finally { setDailyReportLoading(false); } }, [enableDailyReport]); const fetchReceivable = useCallback(async () => { if (!enableReceivable) return; try { setReceivableLoading(true); setReceivableError(null); const apiData = await fetchApi('receivables/summary'); setReceivableData(transformReceivableResponse(apiData)); } catch (err) { setReceivableError(err instanceof Error ? err.message : '데이터 로딩 실패'); } finally { setReceivableLoading(false); } }, [enableReceivable]); const fetchDebtCollection = useCallback(async () => { if (!enableDebtCollection) return; try { setDebtCollectionLoading(true); setDebtCollectionError(null); const apiData = await fetchApi('bad-debts/summary'); setDebtCollectionData(transformDebtCollectionResponse(apiData)); } catch (err) { setDebtCollectionError(err instanceof Error ? err.message : '데이터 로딩 실패'); } finally { setDebtCollectionLoading(false); } }, [enableDebtCollection]); const fetchMonthlyExpense = useCallback(async () => { if (!enableMonthlyExpense) return; try { setMonthlyExpenseLoading(true); setMonthlyExpenseError(null); const apiData = await fetchApi('expected-expenses/summary'); setMonthlyExpenseData(transformMonthlyExpenseResponse(apiData)); } catch (err) { setMonthlyExpenseError(err instanceof Error ? err.message : '데이터 로딩 실패'); } finally { setMonthlyExpenseLoading(false); } }, [enableMonthlyExpense]); const fetchCardManagement = useCallback(async () => { if (!enableCardManagement) return; try { setCardManagementLoading(true); setCardManagementError(null); const apiData = await fetchApi('card-transactions/summary'); setCardManagementData(transformCardManagementResponse(apiData, cardManagementFallback)); } catch (err) { setCardManagementError(err instanceof Error ? err.message : '데이터 로딩 실패'); } finally { setCardManagementLoading(false); } }, [enableCardManagement, cardManagementFallback]); // 전체 refetch const refetchAll = useCallback(() => { fetchDailyReport(); fetchReceivable(); fetchDebtCollection(); fetchMonthlyExpense(); fetchCardManagement(); }, [fetchDailyReport, fetchReceivable, fetchDebtCollection, fetchMonthlyExpense, fetchCardManagement]); // 초기 로드 useEffect(() => { refetchAll(); }, [refetchAll]); return { dailyReport: { data: dailyReportData, loading: dailyReportLoading, error: dailyReportError, }, receivable: { data: receivableData, loading: receivableLoading, error: receivableError, }, debtCollection: { data: debtCollectionData, loading: debtCollectionLoading, error: debtCollectionError, }, monthlyExpense: { data: monthlyExpenseData, loading: monthlyExpenseLoading, error: monthlyExpenseError, }, cardManagement: { data: cardManagementData, loading: cardManagementLoading, error: cardManagementError, }, refetchAll, }; }