import React, { memo, useEffect, useRef, useState } from 'react'; import type { ChangeDir, TickerData } from '../../hooks/useMarketTicker'; import { coerceFiniteNumber, safePercentFromRate, safeToFixed } from '../../utils/safeFormat'; function fmtKrw(price: number | null | undefined | unknown): string { const p = coerceFiniteNumber(price); if (p == null) return '-'; if (p >= 1_000_000) return p.toLocaleString('ko-KR', { maximumFractionDigits: 0 }); if (p >= 1_000) return p.toLocaleString('ko-KR', { maximumFractionDigits: 0 }); if (p >= 1) return p.toLocaleString('ko-KR', { maximumFractionDigits: 2 }); if (p >= 0.01) return safeToFixed(p, 4, '-'); return safeToFixed(p, 8, '-'); } function fmtPct(rate: number | null | undefined | unknown): string { return safePercentFromRate(rate, 2).replace('—', '-'); } const ChangeArrow = memo(function ChangeArrow({ change }: { change: ChangeDir }) { if (change === 'RISE') return ▲; if (change === 'FALL') return ▼; return ─; }); interface Props { market: string; ticker?: TickerData; /** 카드 메타 행 — 현재가만 간략 표시 */ compact?: boolean; /** compact 시 "현재가" 라벨 표시 (기본 true) */ showPriceLabel?: boolean; } const VirtualTargetQuote: React.FC = ({ market, ticker, compact = false, showPriceLabel = true }) => { const code = market.replace(/^KRW-/, ''); const change: ChangeDir = ticker?.change ?? 'EVEN'; const colorCls = change === 'RISE' ? 'vtd-target-up' : change === 'FALL' ? 'vtd-target-dn' : 'vtd-target-even'; const [flashClass, setFlashClass] = useState(''); const prevPriceRef = useRef(null); useEffect(() => { const price = ticker?.tradePrice ?? null; if (price === null) return; const prev = prevPriceRef.current; if (prev !== null && prev !== price) { const cls = price > prev ? 'vtd-target-quote--flash-rise' : 'vtd-target-quote--flash-fall'; setFlashClass(cls); const t = setTimeout(() => setFlashClass(''), 700); prevPriceRef.current = price; return () => clearTimeout(t); } prevPriceRef.current = price; }, [ticker?.tradePrice]); if (compact) { return ( {showPriceLabel && 현재가} {ticker ? fmtKrw(ticker.tradePrice) : '-'} {ticker ? fmtPct(ticker.changeRate) : '-'} ); } return ( {code}/KRW {ticker ? fmtKrw(ticker.tradePrice) : '-'} {ticker ? fmtPct(ticker.changeRate) : '-'} ); }; export default VirtualTargetQuote;