가상투자 종목카드박스 레이아웃 수정

This commit is contained in:
Macbook
2026-05-26 16:42:57 +09:00
parent 7cf43609dc
commit c0d21ac825
25 changed files with 1632 additions and 61 deletions
@@ -12,6 +12,10 @@ import VirtualLiveBadge from './VirtualLiveBadge';
import VirtualTargetQuote from './VirtualTargetQuote';
import VirtualTargetCardChart from './VirtualTargetCardChart';
import VirtualTargetSignalPanel from './VirtualTargetSignalPanel';
import VirtualTargetCardFoot from './VirtualTargetCardFoot';
import { candleTypeToTimeframe } from '../../utils/strategyToChartIndicators';
import { normalizeStartCandleType } from '../../utils/strategyStartNodes';
import type { Timeframe } from '../../types';
interface Props {
market: string;
@@ -20,6 +24,8 @@ interface Props {
strategyId: number | null;
globalStrategyId: number | null;
onStrategyChange?: (strategyId: number | null) => void;
candleType: string;
onCandleTypeChange?: (candleType: string) => void;
snapshot: VirtualIndicatorSnapshot | undefined;
running: boolean;
liveStatus?: VirtualLiveStatus;
@@ -41,6 +47,8 @@ const VirtualTargetFocusView: React.FC<Props> = ({
strategyId,
globalStrategyId,
onStrategyChange,
candleType,
onCandleTypeChange,
snapshot,
running,
liveStatus = 'idle',
@@ -55,7 +63,6 @@ const VirtualTargetFocusView: React.FC<Props> = ({
}) => {
const ko = getKoreanName(market);
const sym = market.replace(/^KRW-/, '');
const tf = snapshot?.timeframe ?? '—';
const receiveSignal = useMemo(() => {
if (!running) return null;
@@ -63,6 +70,8 @@ const VirtualTargetFocusView: React.FC<Props> = ({
}, [running, lastTickAt, snapshot?.updatedAt]);
const receiving = useLiveReceiveFlash(receiveSignal, running);
const highlightReceiving = chartLiveReceiveHighlight && receiving;
const evalCandleType = normalizeStartCandleType(candleType);
const chartTimeframe = candleTypeToTimeframe(evalCandleType) as Timeframe;
return (
<div className={`vtd-focus-wrap${highlightReceiving ? ' vtd-focus-wrap--receiving' : ''}`}>
@@ -72,23 +81,6 @@ const VirtualTargetFocusView: React.FC<Props> = ({
<span className="vtd-card-ko">{ko}</span>
<span className="vtd-card-sym">{sym}</span>
</div>
<label className="vtd-card-strategy-field" onClick={e => e.stopPropagation()}>
<select
className="vtd-card-strategy-select"
aria-label="투자전략"
value={strategyId ?? globalStrategyId ?? ''}
onChange={e => {
const v = e.target.value;
onStrategyChange?.(v ? Number(v) : null);
}}
>
<option value=""> </option>
{strategies.map(s => (
<option key={s.id} value={s.id}>{s.name}</option>
))}
</select>
</label>
<span className="vtd-card-tf"> {tf}</span>
{running && <VirtualLiveBadge status={liveStatus} receiving={receiving} />}
</div>
<button
@@ -123,6 +115,7 @@ const VirtualTargetFocusView: React.FC<Props> = ({
chartRealtimeSource={chartRealtimeSource}
chartSeriesPriceLabels={chartSeriesPriceLabels}
fillHeight
chartTimeframe={chartTimeframe}
/>
</div>
</section>
@@ -137,6 +130,16 @@ const VirtualTargetFocusView: React.FC<Props> = ({
</div>
</section>
</div>
<VirtualTargetCardFoot
snapshot={snapshot}
strategies={strategies}
strategyId={strategyId}
globalStrategyId={globalStrategyId}
candleType={evalCandleType}
onStrategyChange={onStrategyChange}
onCandleTypeChange={onCandleTypeChange}
/>
</div>
);
};