feat(WEB): CEO 대시보드 Phase 2 API 연동 완료
- StatusBoard(현황판) API Hook 및 타입 추가 - TodayIssue(오늘의 이슈) API Hook 및 타입 추가 - Calendar(캘린더) API Hook 및 타입 추가 - Vat(부가세) API Hook 및 타입 추가 - Entertainment(접대비) API Hook 및 타입 추가 - Welfare(복리후생비) API Hook 및 타입 추가 - CEODashboard.tsx에 모든 Phase 2 Hook 통합 - API 응답 → Frontend 타입 변환 transformer 추가 - WelfareCalculationType 'percentage' → 'ratio' 타입 일치 수정
This commit is contained in:
@@ -10,6 +10,12 @@ import type {
|
||||
BadDebtApiResponse,
|
||||
ExpectedExpenseApiResponse,
|
||||
CardTransactionApiResponse,
|
||||
StatusBoardApiResponse,
|
||||
TodayIssueApiResponse,
|
||||
CalendarApiResponse,
|
||||
VatApiResponse,
|
||||
EntertainmentApiResponse,
|
||||
WelfareApiResponse,
|
||||
} from './types';
|
||||
|
||||
import type {
|
||||
@@ -18,8 +24,16 @@ import type {
|
||||
DebtCollectionData,
|
||||
MonthlyExpenseData,
|
||||
CardManagementData,
|
||||
TodayIssueItem,
|
||||
TodayIssueListItem,
|
||||
TodayIssueListBadgeType,
|
||||
CalendarScheduleItem,
|
||||
CheckPoint,
|
||||
CheckPointType,
|
||||
VatData,
|
||||
EntertainmentData,
|
||||
WelfareData,
|
||||
HighlightColor,
|
||||
} from '@/components/business/CEODashboard/types';
|
||||
|
||||
// ============================================
|
||||
@@ -428,4 +442,201 @@ export function transformCardManagementResponse(
|
||||
],
|
||||
checkPoints: generateCardManagementCheckPoints(api),
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 6. StatusBoard 변환
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* StatusBoard API 응답 → Frontend 타입 변환
|
||||
* API 응답 형식이 TodayIssueItem과 거의 동일하므로 단순 매핑
|
||||
*/
|
||||
export function transformStatusBoardResponse(api: StatusBoardApiResponse): TodayIssueItem[] {
|
||||
return api.items.map((item) => ({
|
||||
id: item.id,
|
||||
label: item.label,
|
||||
count: item.count,
|
||||
path: item.path,
|
||||
isHighlighted: item.isHighlighted,
|
||||
}));
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 7. TodayIssue 변환
|
||||
// ============================================
|
||||
|
||||
/** 유효한 뱃지 타입 목록 */
|
||||
const VALID_BADGE_TYPES: TodayIssueListBadgeType[] = [
|
||||
'수주 성공',
|
||||
'주식 이슈',
|
||||
'직정 제고',
|
||||
'지출예상내역서',
|
||||
'세금 신고',
|
||||
'결재 요청',
|
||||
'기타',
|
||||
];
|
||||
|
||||
/**
|
||||
* API 뱃지 문자열 → Frontend 뱃지 타입 변환
|
||||
* 유효하지 않은 뱃지는 '기타'로 폴백
|
||||
*/
|
||||
function validateBadgeType(badge: string): TodayIssueListBadgeType {
|
||||
if (VALID_BADGE_TYPES.includes(badge as TodayIssueListBadgeType)) {
|
||||
return badge as TodayIssueListBadgeType;
|
||||
}
|
||||
return '기타';
|
||||
}
|
||||
|
||||
/**
|
||||
* TodayIssue API 응답 → Frontend 타입 변환
|
||||
* 오늘의 이슈 리스트 데이터 변환
|
||||
*/
|
||||
export function transformTodayIssueResponse(api: TodayIssueApiResponse): {
|
||||
items: TodayIssueListItem[];
|
||||
totalCount: number;
|
||||
} {
|
||||
return {
|
||||
items: api.items.map((item) => ({
|
||||
id: item.id,
|
||||
badge: validateBadgeType(item.badge),
|
||||
content: item.content,
|
||||
time: item.time,
|
||||
date: item.date,
|
||||
needsApproval: item.needsApproval ?? false,
|
||||
path: item.path,
|
||||
})),
|
||||
totalCount: api.total_count,
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 8. Calendar 변환
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* Calendar API 응답 → Frontend 타입 변환
|
||||
* API 응답 형식이 CalendarScheduleItem과 동일하므로 단순 매핑
|
||||
*/
|
||||
export function transformCalendarResponse(api: CalendarApiResponse): {
|
||||
items: CalendarScheduleItem[];
|
||||
totalCount: number;
|
||||
} {
|
||||
return {
|
||||
items: api.items.map((item) => ({
|
||||
id: item.id,
|
||||
title: item.title,
|
||||
startDate: item.startDate,
|
||||
endDate: item.endDate,
|
||||
startTime: item.startTime,
|
||||
endTime: item.endTime,
|
||||
isAllDay: item.isAllDay,
|
||||
type: item.type,
|
||||
department: item.department,
|
||||
personName: item.personName,
|
||||
color: item.color,
|
||||
})),
|
||||
totalCount: api.total_count,
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 9. Vat 변환
|
||||
// ============================================
|
||||
|
||||
/** 유효한 하이라이트 색상 목록 */
|
||||
const VALID_HIGHLIGHT_COLORS: HighlightColor[] = ['red', 'green', 'blue'];
|
||||
|
||||
/**
|
||||
* API 색상 문자열 → Frontend 하이라이트 색상 변환
|
||||
* 유효하지 않은 색상은 'blue'로 폴백
|
||||
*/
|
||||
function validateHighlightColor(color: string): HighlightColor {
|
||||
if (VALID_HIGHLIGHT_COLORS.includes(color as HighlightColor)) {
|
||||
return color as HighlightColor;
|
||||
}
|
||||
return 'blue';
|
||||
}
|
||||
|
||||
/**
|
||||
* Vat API 응답 → Frontend 타입 변환
|
||||
* 부가세 현황 데이터 변환
|
||||
*/
|
||||
export function transformVatResponse(api: VatApiResponse): VatData {
|
||||
return {
|
||||
cards: api.cards.map((card) => ({
|
||||
id: card.id,
|
||||
label: card.label,
|
||||
amount: card.amount,
|
||||
subLabel: card.subLabel,
|
||||
unit: card.unit,
|
||||
})),
|
||||
checkPoints: api.check_points.map((cp) => ({
|
||||
id: cp.id,
|
||||
type: cp.type as CheckPointType,
|
||||
message: cp.message,
|
||||
highlights: cp.highlights?.map((h) => ({
|
||||
text: h.text,
|
||||
color: validateHighlightColor(h.color),
|
||||
})),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 10. Entertainment 변환
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* Entertainment API 응답 → Frontend 타입 변환
|
||||
* 접대비 현황 데이터 변환
|
||||
*/
|
||||
export function transformEntertainmentResponse(api: EntertainmentApiResponse): EntertainmentData {
|
||||
return {
|
||||
cards: api.cards.map((card) => ({
|
||||
id: card.id,
|
||||
label: card.label,
|
||||
amount: card.amount,
|
||||
subLabel: card.subLabel,
|
||||
unit: card.unit,
|
||||
})),
|
||||
checkPoints: api.check_points.map((cp) => ({
|
||||
id: cp.id,
|
||||
type: cp.type as CheckPointType,
|
||||
message: cp.message,
|
||||
highlights: cp.highlights?.map((h) => ({
|
||||
text: h.text,
|
||||
color: validateHighlightColor(h.color),
|
||||
})),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 11. Welfare 변환
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* Welfare API 응답 → Frontend 타입 변환
|
||||
* 복리후생비 현황 데이터 변환
|
||||
*/
|
||||
export function transformWelfareResponse(api: WelfareApiResponse): WelfareData {
|
||||
return {
|
||||
cards: api.cards.map((card) => ({
|
||||
id: card.id,
|
||||
label: card.label,
|
||||
amount: card.amount,
|
||||
subLabel: card.subLabel,
|
||||
unit: card.unit,
|
||||
})),
|
||||
checkPoints: api.check_points.map((cp) => ({
|
||||
id: cp.id,
|
||||
type: cp.type as CheckPointType,
|
||||
message: cp.message,
|
||||
highlights: cp.highlights?.map((h) => ({
|
||||
text: h.text,
|
||||
color: validateHighlightColor(h.color),
|
||||
})),
|
||||
})),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user