Files
goldenChart/frontend/src/components/virtual/VirtualSignalEqualizer.tsx
T
2026-05-29 00:46:20 +09:00

73 lines
2.0 KiB
TypeScript

import React, { useMemo } from 'react';
import { coerceFiniteNumber } from '../../utils/safeFormat';
const SEGMENTS = 25;
interface Props {
matchRate: number;
}
const VirtualSignalEqualizer: React.FC<Props> = ({ matchRate }) => {
const rate = coerceFiniteNumber(matchRate) ?? 0;
const litCount = useMemo(
() => Math.round((Math.min(100, Math.max(0, rate)) / 100) * SEGMENTS),
[rate],
);
const segments = useMemo(() => {
const items: Array<{ lit: boolean; tone: 'red' | 'gold' | 'blue' | 'peak' }> = [];
const third = SEGMENTS / 3;
for (let i = 0; i < SEGMENTS; i++) {
const lit = i < litCount;
if (!lit) {
items.push({ lit: false, tone: 'blue' });
continue;
}
let tone: 'red' | 'gold' | 'blue' | 'peak';
if (rate >= 100 && i === SEGMENTS - 1) {
tone = 'peak';
} else if (i < third) {
tone = 'red';
} else if (i < third * 2) {
tone = 'gold';
} else {
tone = 'blue';
}
items.push({ lit: true, tone });
}
return items;
}, [litCount, rate]);
/** 신호등 열 높이에 맞춘 20% 눈금 (가상매매·알림 공통) */
const ticks = [100, 80, 60, 40, 20, 0];
return (
<div className="vtd-sig-eq">
<div className="vtd-sig-eq-scale" aria-hidden>
{ticks.map(t => (
<span key={t} className="vtd-sig-eq-tick">{t}%</span>
))}
</div>
<div className="vtd-sig-eq-bar-wrap">
<div className="vtd-sig-eq-bar">
{segments.map((seg, i) => (
<div
key={i}
className={[
'vtd-sig-eq-seg',
seg.lit ? 'vtd-sig-eq-seg--lit' : '',
seg.lit ? `vtd-sig-eq-seg--${seg.tone}` : '',
].filter(Boolean).join(' ')}
/>
))}
</div>
{rate >= 100 && (
<div className="vtd-sig-eq-badge">100% MATCH</div>
)}
</div>
</div>
);
};
export default VirtualSignalEqualizer;