chore(WEB): actions.ts 에러 핸들링 및 CEO 대시보드 개선

- 전체 모듈 actions.ts redirect 에러 핸들링 추가
- CEODashboard DetailModal 추가
- MonthlyExpenseSection 개선
- fetch-wrapper redirect 에러 처리
- redirect-error 유틸 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
byeongcheolryu
2026-01-08 18:41:15 +09:00
parent 9885085259
commit 0d539628f3
61 changed files with 1226 additions and 359 deletions

View File

@@ -1,7 +1,7 @@
'use server';
import { isRedirectError } from 'next/dist/client/components/redirect';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { serverFetch } from '@/lib/api/fetch-wrapper';
import type { ExpectedExpenseRecord, TransactionType, PaymentStatus, ApprovalStatus } from './types';
@@ -190,7 +190,7 @@ export async function getExpectedExpenses(params?: {
},
};
} catch (error) {
if (isRedirectError(error)) throw error;
if (isNextRedirectError(error)) throw error;
console.error('[ExpectedExpenseActions] getExpectedExpenses error:', error);
return {
success: false,
@@ -239,7 +239,7 @@ export async function getExpectedExpenseById(id: string): Promise<{
data: transformApiToFrontend(result.data),
};
} catch (error) {
if (isRedirectError(error)) throw error;
if (isNextRedirectError(error)) throw error;
console.error('[ExpectedExpenseActions] getExpectedExpenseById error:', error);
return {
success: false,
@@ -281,7 +281,7 @@ export async function createExpectedExpense(
data: transformApiToFrontend(result.data),
};
} catch (error) {
if (isRedirectError(error)) throw error;
if (isNextRedirectError(error)) throw error;
console.error('[ExpectedExpenseActions] createExpectedExpense error:', error);
return {
success: false,
@@ -324,7 +324,7 @@ export async function updateExpectedExpense(
data: transformApiToFrontend(result.data),
};
} catch (error) {
if (isRedirectError(error)) throw error;
if (isNextRedirectError(error)) throw error;
console.error('[ExpectedExpenseActions] updateExpectedExpense error:', error);
return {
success: false,
@@ -356,7 +356,7 @@ export async function deleteExpectedExpense(id: string): Promise<{ success: bool
return { success: true };
} catch (error) {
if (isRedirectError(error)) throw error;
if (isNextRedirectError(error)) throw error;
console.error('[ExpectedExpenseActions] deleteExpectedExpense error:', error);
return {
success: false,
@@ -400,7 +400,7 @@ export async function deleteExpectedExpenses(ids: string[]): Promise<{
deletedCount: result.data?.deleted_count,
};
} catch (error) {
if (isRedirectError(error)) throw error;
if (isNextRedirectError(error)) throw error;
console.error('[ExpectedExpenseActions] deleteExpectedExpenses error:', error);
return {
success: false,
@@ -448,7 +448,7 @@ export async function updateExpectedPaymentDate(
updatedCount: result.data?.updated_count,
};
} catch (error) {
if (isRedirectError(error)) throw error;
if (isNextRedirectError(error)) throw error;
console.error('[ExpectedExpenseActions] updateExpectedPaymentDate error:', error);
return {
success: false,
@@ -507,7 +507,7 @@ export async function getExpectedExpenseSummary(params?: {
data: result.data,
};
} catch (error) {
if (isRedirectError(error)) throw error;
if (isNextRedirectError(error)) throw error;
console.error('[ExpectedExpenseActions] getExpectedExpenseSummary error:', error);
return {
success: false,
@@ -552,7 +552,7 @@ export async function getClients(): Promise<{
})),
};
} catch (error) {
if (isRedirectError(error)) throw error;
if (isNextRedirectError(error)) throw error;
console.error('[ExpectedExpenseActions] getClients error:', error);
return { success: false, data: [], error: '서버 오류가 발생했습니다.' };
}
@@ -596,7 +596,7 @@ export async function getBankAccounts(): Promise<{
})),
};
} catch (error) {
if (isRedirectError(error)) throw error;
if (isNextRedirectError(error)) throw error;
console.error('[ExpectedExpenseActions] getBankAccounts error:', error);
return { success: false, data: [], error: '서버 오류가 발생했습니다.' };
}