mda-snp-batch 기반으로 snp-sync-batch 프로젝트 생성 - 프론트엔드: Thymeleaf → React + TypeScript + Vite + Tailwind CSS 전환 - 컨텍스트: /snp-sync, 포트 8051 - 재수집(Recollection) 관련 코드 제거 - displayName → job_schedule.description 기반으로 전환 - 누락 API 추가 (statistics, jobs/detail, executions/recent) - 실행 이력 조회 속도 개선 (JDBC 경량 쿼리) - 스케줄 CRUD API 메서드 매핑 수정 (PUT/DELETE) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
75 lines
2.1 KiB
TypeScript
75 lines
2.1 KiB
TypeScript
interface BarValue {
|
|
color: string;
|
|
value: number;
|
|
}
|
|
|
|
interface BarData {
|
|
label: string;
|
|
values: BarValue[];
|
|
}
|
|
|
|
interface Props {
|
|
data: BarData[];
|
|
height?: number;
|
|
}
|
|
|
|
export default function BarChart({ data, height = 200 }: Props) {
|
|
const maxTotal = Math.max(...data.map((d) => d.values.reduce((sum, v) => sum + v.value, 0)), 1);
|
|
|
|
return (
|
|
<div className="w-full">
|
|
<div className="flex items-end gap-1" style={{ height }}>
|
|
{data.map((bar, i) => {
|
|
const total = bar.values.reduce((sum, v) => sum + v.value, 0);
|
|
const ratio = total / maxTotal;
|
|
|
|
return (
|
|
<div key={i} className="flex-1 flex flex-col justify-end h-full min-w-0">
|
|
<div
|
|
className="w-full rounded-t overflow-hidden"
|
|
style={{ height: `${ratio * 100}%` }}
|
|
title={bar.values.map((v) => `${v.color}: ${v.value}`).join(', ')}
|
|
>
|
|
{bar.values
|
|
.filter((v) => v.value > 0)
|
|
.map((v, j) => {
|
|
const segmentRatio = total > 0 ? (v.value / total) * 100 : 0;
|
|
return (
|
|
<div
|
|
key={j}
|
|
className={colorToClass(v.color)}
|
|
style={{ height: `${segmentRatio}%` }}
|
|
/>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
<div className="flex gap-1 mt-1">
|
|
{data.map((bar, i) => (
|
|
<div key={i} className="flex-1 min-w-0">
|
|
<p className="text-[10px] text-gray-500 text-center truncate" title={bar.label}>
|
|
{bar.label}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function colorToClass(color: string): string {
|
|
const map: Record<string, string> = {
|
|
green: 'bg-green-500',
|
|
red: 'bg-red-500',
|
|
gray: 'bg-gray-400',
|
|
blue: 'bg-blue-500',
|
|
yellow: 'bg-yellow-500',
|
|
orange: 'bg-orange-500',
|
|
indigo: 'bg-indigo-500',
|
|
};
|
|
return map[color] ?? color;
|
|
}
|