'use server'; import { executeServerAction, type ActionResult } from '@/lib/api/execute-server-action'; import type { ComprehensiveAnalysisData } from './types'; const API_URL = process.env.NEXT_PUBLIC_API_URL; // ===== API 응답 타입 ===== interface TodayIssueItemApi { id: string; category: string; description: string; requires_approval: boolean; time: string; } interface TodayIssueSectionApi { filter_options: string[]; items: TodayIssueItemApi[]; } interface CheckPointApi { id: string; type: 'success' | 'warning' | 'error' | 'info'; message: string; highlight?: string; } interface AmountCardApi { id: string; label: string; amount: number; sub_amount?: number; sub_label?: string; previous_amount?: number; previous_label?: string; } interface ExpenseSectionApi { cards: AmountCardApi[]; check_points: CheckPointApi[]; } interface ReceivableSectionApi extends ExpenseSectionApi { has_detail_button: boolean; detail_button_label: string; detail_button_path: string; } interface ComprehensiveAnalysisDataApi { today_issue: TodayIssueSectionApi; monthly_expense: ExpenseSectionApi; card_management: ExpenseSectionApi; entertainment: ExpenseSectionApi; welfare: ExpenseSectionApi; receivable: ReceivableSectionApi; debt_collection: ExpenseSectionApi; } // ===== API → Frontend 변환 ===== function transformCheckPoint(item: CheckPointApi): ComprehensiveAnalysisData['monthlyExpense']['checkPoints'][0] { return { id: item.id, type: item.type, message: item.message, highlight: item.highlight }; } function transformAmountCard(item: AmountCardApi): ComprehensiveAnalysisData['monthlyExpense']['cards'][0] { return { id: item.id, label: item.label, amount: item.amount, subAmount: item.sub_amount, subLabel: item.sub_label, previousAmount: item.previous_amount, previousLabel: item.previous_label, }; } function transformTodayIssueItem(item: TodayIssueItemApi): ComprehensiveAnalysisData['todayIssue']['items'][0] { return { id: item.id, category: item.category, description: item.description, requiresApproval: item.requires_approval, time: item.time }; } function transformExpenseSection(section: ExpenseSectionApi): ComprehensiveAnalysisData['monthlyExpense'] { return { cards: section.cards.map(transformAmountCard), checkPoints: section.check_points.map(transformCheckPoint) }; } function transformReceivableSection(section: ReceivableSectionApi): ComprehensiveAnalysisData['receivable'] { return { cards: section.cards.map(transformAmountCard), checkPoints: section.check_points.map(transformCheckPoint), hasDetailButton: section.has_detail_button, detailButtonLabel: section.detail_button_label, detailButtonPath: section.detail_button_path, }; } function transformAnalysisData(data: ComprehensiveAnalysisDataApi): ComprehensiveAnalysisData { return { todayIssue: { filterOptions: data.today_issue.filter_options, items: data.today_issue.items.map(transformTodayIssueItem) }, monthlyExpense: transformExpenseSection(data.monthly_expense), cardManagement: transformExpenseSection(data.card_management), entertainment: transformExpenseSection(data.entertainment), welfare: transformExpenseSection(data.welfare), receivable: transformReceivableSection(data.receivable), debtCollection: transformExpenseSection(data.debt_collection), }; } // ===== 종합 분석 데이터 조회 ===== export async function getComprehensiveAnalysis(params?: { date?: string; }): Promise> { const searchParams = new URLSearchParams(); if (params?.date) searchParams.set('date', params.date); const queryString = searchParams.toString(); return executeServerAction({ url: `${API_URL}/api/v1/comprehensive-analysis${queryString ? `?${queryString}` : ''}`, transform: (data: ComprehensiveAnalysisDataApi) => transformAnalysisData(data), errorMessage: '종합 분석 조회에 실패했습니다.', }); } // ===== 이슈 승인 ===== export async function approveIssue(issueId: string): Promise { return executeServerAction({ url: `${API_URL}/api/v1/approvals/${issueId}/approve`, method: 'POST', errorMessage: '승인에 실패했습니다.', }); } // ===== 이슈 반려 ===== export async function rejectIssue(issueId: string, reason?: string): Promise { return executeServerAction({ url: `${API_URL}/api/v1/approvals/${issueId}/reject`, method: 'POST', body: { comment: reason }, errorMessage: '반려에 실패했습니다.', }); }