signal-batch/frontend/src/components/charts/LineChart.tsx
htlee 23e33fe4bb feat: Phase 2 — 데이터 파이프라인 + 해구 통계 페이지
- DataPipeline: 4단계 흐름도(PipelineChart), L1/L2/L3 캐시 현황, 일별 처리량 추이(LineChart), 최근 실행 이력
- AreaStats: 대해구별 선박 통계 테이블, 처리량(파티션 크기), 데이터 품질 검증
- LineChart, PipelineChart 차트 컴포넌트 신규
- API 타입 추가 (CacheDetails, HaeguStat, ThroughputMetrics, DataQuality)
- monitorApi에 getCacheDetails, getHaeguRealtimeStats, getQuality 추가
- i18n pipeline.*, area.* 번역 키 추가 (ko/en)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 17:55:52 +09:00

80 lines
1.9 KiB
TypeScript

import {
LineChart as RechartsLineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
Legend,
} from 'recharts'
interface LineSeries {
dataKey: string
color: string
name?: string
}
interface LineChartProps {
data: Record<string, unknown>[]
series: LineSeries[]
xKey: string
height?: number
label?: string
}
export default function LineChart({
data,
series,
xKey,
height = 240,
label,
}: LineChartProps) {
return (
<div>
{label && <div className="mb-2 text-sm font-medium text-muted">{label}</div>}
<ResponsiveContainer width="100%" height={height}>
<RechartsLineChart data={data} margin={{ top: 4, right: 4, bottom: 4, left: 4 }}>
<CartesianGrid strokeDasharray="3 3" stroke="var(--sb-border)" />
<XAxis
dataKey={xKey}
tick={{ fontSize: 12, fill: 'var(--sb-text-muted)' }}
axisLine={{ stroke: 'var(--sb-border)' }}
tickLine={false}
/>
<YAxis
tick={{ fontSize: 12, fill: 'var(--sb-text-muted)' }}
axisLine={false}
tickLine={false}
/>
<Tooltip
contentStyle={{
backgroundColor: 'var(--sb-surface)',
border: '1px solid var(--sb-border)',
borderRadius: 'var(--sb-radius)',
fontSize: 12,
}}
/>
{series.length > 1 && (
<Legend
wrapperStyle={{ fontSize: 12, color: 'var(--sb-text-muted)' }}
/>
)}
{series.map(s => (
<Line
key={s.dataKey}
type="monotone"
dataKey={s.dataKey}
stroke={s.color}
name={s.name ?? s.dataKey}
strokeWidth={2}
dot={false}
activeDot={{ r: 4 }}
/>
))}
</RechartsLineChart>
</ResponsiveContainer>
</div>
)
}