Files
sam-react-prod/src/hooks/useCEODashboard.ts

422 lines
13 KiB
TypeScript
Raw Normal View History

'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<T>(endpoint: string): Promise<T> {
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<DailyReportData | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchData = useCallback(async () => {
try {
setLoading(true);
setError(null);
const apiData = await fetchApi<DailyReportApiResponse>('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<ReceivableData | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchData = useCallback(async () => {
try {
setLoading(true);
setError(null);
const apiData = await fetchApi<ReceivablesApiResponse>('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<DebtCollectionData | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchData = useCallback(async () => {
try {
setLoading(true);
setError(null);
const apiData = await fetchApi<BadDebtApiResponse>('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<MonthlyExpenseData | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchData = useCallback(async () => {
try {
setLoading(true);
setError(null);
const apiData = await fetchApi<ExpectedExpenseApiResponse>('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<CardManagementData | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchData = useCallback(async () => {
try {
setLoading(true);
setError(null);
const apiData = await fetchApi<CardTransactionApiResponse>('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<DailyReportData | null>(null);
const [dailyReportLoading, setDailyReportLoading] = useState(enableDailyReport);
const [dailyReportError, setDailyReportError] = useState<string | null>(null);
const [receivableData, setReceivableData] = useState<ReceivableData | null>(null);
const [receivableLoading, setReceivableLoading] = useState(enableReceivable);
const [receivableError, setReceivableError] = useState<string | null>(null);
const [debtCollectionData, setDebtCollectionData] = useState<DebtCollectionData | null>(null);
const [debtCollectionLoading, setDebtCollectionLoading] = useState(enableDebtCollection);
const [debtCollectionError, setDebtCollectionError] = useState<string | null>(null);
const [monthlyExpenseData, setMonthlyExpenseData] = useState<MonthlyExpenseData | null>(null);
const [monthlyExpenseLoading, setMonthlyExpenseLoading] = useState(enableMonthlyExpense);
const [monthlyExpenseError, setMonthlyExpenseError] = useState<string | null>(null);
const [cardManagementData, setCardManagementData] = useState<CardManagementData | null>(null);
const [cardManagementLoading, setCardManagementLoading] = useState(enableCardManagement);
const [cardManagementError, setCardManagementError] = useState<string | null>(null);
// 개별 fetch 함수들
const fetchDailyReport = useCallback(async () => {
if (!enableDailyReport) return;
try {
setDailyReportLoading(true);
setDailyReportError(null);
const apiData = await fetchApi<DailyReportApiResponse>('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<ReceivablesApiResponse>('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<BadDebtApiResponse>('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<ExpectedExpenseApiResponse>('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<CardTransactionApiResponse>('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,
};
}