가상투자 화면 목록 선택 동작

This commit is contained in:
Macbook
2026-05-25 14:05:13 +09:00
parent 20f11f6c4b
commit 3102169541
24 changed files with 130 additions and 27 deletions
@@ -4,7 +4,7 @@ import type { StrategyDto } from '../../utils/backendApi';
import type { VirtualIndicatorSnapshot } from '../../hooks/useVirtualIndicatorSnapshots';
import { useLiveReceiveFlash } from '../../hooks/useLiveReceiveFlash';
import type { ChartRealtimeSource } from '../../hooks/useChartRealtimeData';
import { buildConditionMetrics } from '../../utils/virtualSignalMetrics';
import { buildConditionMetrics, resolveVirtualTradeTiming } from '../../utils/virtualSignalMetrics';
import VirtualLiveBadge from './VirtualLiveBadge';
import type { VirtualLiveStatus } from '../../hooks/useVirtualTargetLiveStatus';
import type { VirtualCardViewMode } from '../../utils/virtualTradingStorage';
@@ -29,6 +29,8 @@ interface Props {
displayMode?: VirtualCardDisplayMode;
onDisplayModeChange?: (mode: VirtualCardDisplayMode) => void;
onEnterFocus?: () => void;
selected?: boolean;
onSelect?: () => void;
theme?: Theme;
chartRealtimeSource?: ChartRealtimeSource;
chartSeriesPriceLabels?: boolean;
@@ -49,6 +51,8 @@ const VirtualTargetCard: React.FC<Props> = ({
displayMode = 'signal',
onDisplayModeChange,
onEnterFocus,
selected = false,
onSelect,
theme = 'dark',
chartRealtimeSource = 'BACKEND_STOMP',
chartSeriesPriceLabels = true,
@@ -59,6 +63,7 @@ const VirtualTargetCard: React.FC<Props> = ({
const rows = snapshot?.rows ?? [];
const metrics = useMemo(() => buildConditionMetrics(rows), [rows]);
const tradeTiming = useMemo(() => resolveVirtualTradeTiming(metrics), [metrics]);
const metCount = metrics.filter(m => m.status === 'match').length;
const evalCount = metrics.filter(m => m.status !== 'unknown').length;
@@ -80,7 +85,20 @@ const VirtualTargetCard: React.FC<Props> = ({
receiving ? 'vtd-card--receiving' : '',
isDetail ? 'vtd-card--detail' : 'vtd-card--summary',
isChart ? 'vtd-card--chart-mode' : '',
selected ? 'vtd-card--selected' : '',
tradeTiming === 'buy' ? 'vtd-card--timing-buy' : '',
tradeTiming === 'sell' ? 'vtd-card--timing-sell' : '',
].filter(Boolean).join(' ')}
onClick={onSelect}
onKeyDown={e => {
if (onSelect && (e.key === 'Enter' || e.key === ' ')) {
e.preventDefault();
onSelect();
}
}}
role={onSelect ? 'button' : undefined}
tabIndex={onSelect ? 0 : undefined}
aria-pressed={onSelect ? selected : undefined}
>
<div className="vtd-card-head">
<div className="vtd-card-head-main">
@@ -122,7 +140,7 @@ const VirtualTargetCard: React.FC<Props> = ({
</svg>
</button>
)}
<div className="vtd-card-mode-toggle" role="group" aria-label="이 종목 표시">
<div className="vtd-card-mode-toggle" role="group" aria-label="이 종목 표시" onClick={e => e.stopPropagation()}>
<button
type="button"
className={`vtd-card-mode-btn${displayMode === 'signal' ? ' vtd-card-mode-btn--on' : ''}`}