Files
sam-react-prod/src/lib/api/dashboard/endpoints.ts
권혁성 fe845227df feat: Phase 2 프론트엔드 타입 및 API 연동
- API 타입 정의 추가 (LoanDashboard, TaxSimulation)
- API 엔드포인트 함수 추가 (endpoints.ts)
- 모달 데이터 훅 생성 (useCardManagementModals.ts)

관련: docs/plans/card-management-section-plan.md
2026-01-22 23:01:22 +09:00

242 lines
6.7 KiB
TypeScript

'use server';
/**
* CEO Dashboard API 엔드포인트 함수
*
* 카드/가지급금 관리 섹션 (cm1-cm4) 데이터 조회
*/
import { apiClient } from '../index';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import type {
ApiResponse,
CardDashboardDetailApiResponse,
LoanDashboardApiResponse,
TaxSimulationApiResponse,
} from './types';
// ============================================
// 에러 핸들링 헬퍼
// ============================================
/**
* 인증 에러인지 확인
*/
function isAuthenticationError(error: unknown): boolean {
if (error && typeof error === 'object') {
const err = error as { status?: number; code?: string; message?: string };
if (err.status === 401) return true;
if (err.code === 'AUTH_ERROR') return true;
if (err.message?.includes('회원정보') || err.message?.includes('인증')) return true;
}
return false;
}
// ============================================
// 카드 거래 대시보드 API
// ============================================
/**
* 카드 거래 대시보드 데이터 조회
* GET /api/v1/card-transactions/dashboard
*
* @returns 카드 거래 요약, 월별 추이, 사용자별 분포, 거래 목록
*/
export async function fetchCardTransactionDashboard(): Promise<ApiResponse<CardDashboardDetailApiResponse>> {
try {
const response = await apiClient.get<ApiResponse<CardDashboardDetailApiResponse>>(
'/card-transactions/dashboard'
);
return response;
} catch (error) {
// Next.js redirect 에러는 전파
if (isNextRedirectError(error)) {
throw error;
}
console.error('[Dashboard] fetchCardTransactionDashboard error:', error);
// 인증 에러인 경우
if (isAuthenticationError(error)) {
return {
success: false,
message: '인증이 만료되었습니다.',
data: {
summary: {
current_month_total: 0,
previous_month_total: 0,
total_count: 0,
current_month_count: 0,
},
monthly_trend: [],
by_user: [],
items: [],
},
};
}
// 기타 에러
return {
success: false,
message: error instanceof Error ? error.message : 'API 요청 실패',
data: {
summary: {
current_month_total: 0,
previous_month_total: 0,
total_count: 0,
current_month_count: 0,
},
monthly_trend: [],
by_user: [],
items: [],
},
};
}
}
// ============================================
// 가지급금 대시보드 API
// ============================================
/**
* 가지급금 대시보드 데이터 조회
* GET /api/v1/loans/dashboard
*
* @returns 가지급금 요약, 월별 추이, 사용자별 분포, 거래 목록
*/
export async function fetchLoanDashboard(): Promise<ApiResponse<LoanDashboardApiResponse>> {
try {
const response = await apiClient.get<ApiResponse<LoanDashboardApiResponse>>(
'/loans/dashboard'
);
return response;
} catch (error) {
// Next.js redirect 에러는 전파
if (isNextRedirectError(error)) {
throw error;
}
console.error('[Dashboard] fetchLoanDashboard error:', error);
// 인증 에러인 경우
if (isAuthenticationError(error)) {
return {
success: false,
message: '인증이 만료되었습니다.',
data: {
summary: {
total_outstanding: 0,
settled_amount: 0,
recognized_interest: 0,
pending_count: 0,
},
monthly_trend: [],
user_distribution: [],
items: [],
},
};
}
// 기타 에러
return {
success: false,
message: error instanceof Error ? error.message : 'API 요청 실패',
data: {
summary: {
total_outstanding: 0,
settled_amount: 0,
recognized_interest: 0,
pending_count: 0,
},
monthly_trend: [],
user_distribution: [],
items: [],
},
};
}
}
// ============================================
// 세금 시뮬레이션 API
// ============================================
/**
* 세금 시뮬레이션 데이터 조회
* GET /api/v1/loans/tax-simulation?year={year}
*
* @param year - 시뮬레이션 연도 (기본값: 현재 연도)
* @returns 가지급금 요약, 법인세 비교, 소득세 비교
*/
export async function fetchTaxSimulation(year?: number): Promise<ApiResponse<TaxSimulationApiResponse>> {
try {
const targetYear = year || new Date().getFullYear();
const response = await apiClient.get<ApiResponse<TaxSimulationApiResponse>>(
'/loans/tax-simulation',
{ params: { year: String(targetYear) } }
);
return response;
} catch (error) {
// Next.js redirect 에러는 전파
if (isNextRedirectError(error)) {
throw error;
}
console.error('[Dashboard] fetchTaxSimulation error:', error);
const currentYear = year || new Date().getFullYear();
// 인증 에러인 경우
if (isAuthenticationError(error)) {
return {
success: false,
message: '인증이 만료되었습니다.',
data: {
year: currentYear,
loan_summary: {
total_outstanding: 0,
recognized_interest: 0,
interest_rate: 0.046,
},
corporate_tax: {
without_loan: { taxable_income: 0, tax_amount: 0 },
with_loan: { taxable_income: 0, tax_amount: 0 },
difference: 0,
rate_info: '법인세 19% 적용',
},
income_tax: {
without_loan: { taxable_income: 0, tax_rate: '0%', tax_amount: 0 },
with_loan: { taxable_income: 0, tax_rate: '35%', tax_amount: 0 },
difference: 0,
breakdown: { income_tax: 0, local_tax: 0, insurance: 0 },
},
},
};
}
// 기타 에러
return {
success: false,
message: error instanceof Error ? error.message : 'API 요청 실패',
data: {
year: currentYear,
loan_summary: {
total_outstanding: 0,
recognized_interest: 0,
interest_rate: 0.046,
},
corporate_tax: {
without_loan: { taxable_income: 0, tax_amount: 0 },
with_loan: { taxable_income: 0, tax_amount: 0 },
difference: 0,
rate_info: '법인세 19% 적용',
},
income_tax: {
without_loan: { taxable_income: 0, tax_rate: '0%', tax_amount: 0 },
with_loan: { taxable_income: 0, tax_rate: '35%', tax_amount: 0 },
difference: 0,
breakdown: { income_tax: 0, local_tax: 0, insurance: 0 },
},
},
};
}
}