import { Card, Col, Row, Typography } from 'antd'; import { IconCash, IconCheck, IconClock, IconAlertTriangle, IconTrendingUp, IconTrendingDown, } from '@tabler/icons-react'; import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis, Tooltip, CartesianGrid, Legend, } from 'recharts'; import PageContainer from '@/components/common/PageContainer'; import MoneyText from '@/components/common/MoneyText'; const { Text } = Typography; const KPI_CARDS = [ { key: 'recruit', label: '모집수수료', value: 124_500_000, delta: +8.2, icon: , color: '#1677FF', bg: '#E6F1FB' }, { key: 'maintain', label: '유지수수료', value: 82_300_000, delta: +3.1, icon: , color: '#0F6E56', bg: '#E1F5EE' }, { key: 'pending', label: '확정 대기', value: 12, delta: -2.0, suffix: '건', icon: , color: '#BA7517', bg: '#FAEEDA' }, { key: 'alert', label: '대사 차이', value: 3, delta: +50.0, suffix: '건', icon: , color: '#E24B4A', bg: '#FCEBEB' }, ]; const MONTHLY_TREND = [ { month: '12월', recruit: 95, maintain: 70, chargeback: 5 }, { month: '1월', recruit: 105, maintain: 72, chargeback: 8 }, { month: '2월', recruit: 110, maintain: 75, chargeback: 6 }, { month: '3월', recruit: 118, maintain: 78, chargeback: 7 }, { month: '4월', recruit: 122, maintain: 80, chargeback: 9 }, { month: '5월', recruit: 125, maintain: 82, chargeback: 4 }, ]; const BATCH_STEPS = [ { name: '데이터 수신', status: 'done', time: '02:14' }, { name: '데이터 변환', status: 'done', time: '00:52' }, { name: '대사 검증', status: 'done', time: '00:21' }, { name: '모집수수료', status: 'done', time: '01:08' }, { name: '유지수수료', status: 'done', time: '00:46' }, { name: '환수/예외', status: 'progress', time: '00:33' }, { name: '오버라이드', status: 'pending' }, { name: '집계', status: 'pending' }, ]; export default function Dashboard() { return ( {/* KPI 카드 4개 */} {KPI_CARDS.map((c) => { const isUp = c.delta >= 0; return (
{c.icon}
{c.label}
{c.suffix === '건' ? c.value.toLocaleString() : ( )} {c.suffix ?? '원'}
{isUp ? : } {Math.abs(c.delta).toFixed(1)}% 전월 대비
); })}
{/* 차트 + 배치 현황 */} 월별 추이 (최근 6개월)} bordered={false} style={{ boxShadow: 'var(--ga-shadow-card)' }} styles={{ body: { padding: 16, height: 280 } }} > 배치 진행 (5월)} bordered={false} style={{ boxShadow: 'var(--ga-shadow-card)' }} styles={{ body: { padding: 16 } }} > {BATCH_STEPS.map((s, i) => { const dotColor = s.status === 'done' ? '#0F6E56' : s.status === 'progress' ? '#1677FF' : '#ddd'; return (
Step {i + 1}. {s.name}
{s.time ?? '-'}
); })} {/* 알림 */} 최근 알림} bordered={false} style={{ boxShadow: 'var(--ga-shadow-card)' }} styles={{ body: { padding: 0 } }} > {[ { tag: '대사불일치', tagColor: '#E24B4A', tagBg: '#FCEBEB', text: '삼성생명 5월 통보액 vs 시스템 계산액 3건 차이', time: '10분 전' }, { tag: '파싱에러', tagColor: '#BA7517', tagBg: '#FAEEDA', text: '한화생명 raw 파일 12행 날짜 형식 오류 (parse_error_log #4521)', time: '1시간 전' }, { tag: '승인대기', tagColor: '#1677FF', tagBg: '#E6F1FB', text: '예외금액 원장 승인 대기 5건 (정산월 202605)', time: '3시간 전' }, ].map((n, i) => (
{n.tag} {n.text} {n.time}
))}
); }