가상투자 화면 추가

This commit is contained in:
Macbook
2026-05-25 13:14:36 +09:00
parent 1fe3e404fa
commit 339e2355eb
23 changed files with 2230 additions and 457 deletions
@@ -0,0 +1,181 @@
import React from 'react';
import type { StrategyDto } from '../../utils/backendApi';
import type { VirtualSessionConfig, VirtualCardViewMode } from '../../utils/virtualTradingStorage';
import type { VirtualCardDisplayMode } from './VirtualTargetCard';
interface Props {
session: Pick<VirtualSessionConfig, 'globalStrategyId' | 'executionType' | 'positionMode' | 'running'>;
strategies: StrategyDto[];
onStrategyChange: (strategyId: number | null) => void;
onExecutionTypeChange: (type: VirtualSessionConfig['executionType']) => void;
onPositionModeChange: (mode: VirtualSessionConfig['positionMode']) => void;
onStart: () => void;
onStop: () => void;
viewMode?: VirtualCardViewMode;
onViewModeChange?: (mode: VirtualCardViewMode) => void;
globalDisplayMode?: VirtualCardDisplayMode;
onGlobalDisplayModeChange?: (mode: VirtualCardDisplayMode) => void;
/** 우측 뷰 토글: full=신호·차트+요약·상세, display-only=요약·상세만, hidden=숨김 */
viewControls?: 'full' | 'display-only' | 'hidden';
}
const VirtualGridUnifiedHeader: React.FC<Props> = ({
session,
strategies,
onStrategyChange,
onExecutionTypeChange,
onPositionModeChange,
onStart,
onStop,
viewMode = 'summary',
onViewModeChange,
globalDisplayMode = 'signal',
onGlobalDisplayModeChange,
viewControls = 'full',
}) => (
<div className="vtd-unified-head">
<span className="vtd-unified-head-title"> </span>
<div className="vtd-unified-head-center">
<div className="vtd-session-field">
<span className="vtd-session-label"></span>
<select
className="vtd-session-select"
value={session.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>
</div>
<div className="vtd-session-field">
<span className="vtd-session-label"></span>
<div className="vtd-view-toggle" role="group" aria-label="실행방식">
<button
type="button"
className={`vtd-view-toggle-btn${session.executionType === 'CANDLE_CLOSE' ? ' vtd-view-toggle-btn--on' : ''}`}
onClick={() => onExecutionTypeChange('CANDLE_CLOSE')}
>
</button>
<button
type="button"
className={`vtd-view-toggle-btn${session.executionType === 'REALTIME_TICK' ? ' vtd-view-toggle-btn--on' : ''}`}
onClick={() => onExecutionTypeChange('REALTIME_TICK')}
>
</button>
</div>
</div>
<div className="vtd-session-field">
<span className="vtd-session-label"> </span>
<div className="vtd-view-toggle" role="group" aria-label="시그널 모드">
<button
type="button"
className={`vtd-view-toggle-btn${session.positionMode === 'LONG_ONLY' ? ' vtd-view-toggle-btn--on' : ''}`}
onClick={() => onPositionModeChange('LONG_ONLY')}
>
</button>
<button
type="button"
className={`vtd-view-toggle-btn${session.positionMode === 'SIGNAL_ONLY' ? ' vtd-view-toggle-btn--on' : ''}`}
onClick={() => onPositionModeChange('SIGNAL_ONLY')}
>
</button>
</div>
</div>
<div className="vtd-session-actions">
<button
type="button"
className="bps-btn vtd-session-btn vtd-session-btn--start"
disabled={session.running}
onClick={onStart}
>
</button>
<button
type="button"
className="bps-btn bps-btn--danger vtd-session-btn"
disabled={!session.running}
onClick={onStop}
>
</button>
</div>
</div>
{viewControls !== 'hidden' && onViewModeChange && (
<div className="vtd-unified-head-right">
{viewControls === 'full' && onGlobalDisplayModeChange && (
<>
<div className="vtd-grid-head-group" role="group" aria-label="전체 종목 신호·차트">
<div className="vtd-view-toggle">
<button
type="button"
className={`vtd-view-toggle-btn${globalDisplayMode === 'signal' ? ' vtd-view-toggle-btn--on' : ''}`}
onClick={() => onGlobalDisplayModeChange('signal')}
>
</button>
<button
type="button"
className={`vtd-view-toggle-btn${globalDisplayMode === 'chart' ? ' vtd-view-toggle-btn--on' : ''}`}
onClick={() => onGlobalDisplayModeChange('chart')}
>
</button>
</div>
</div>
<span className="vtd-grid-head-divider" aria-hidden="true" />
</>
)}
<div className="vtd-grid-head-group" role="group" aria-label="카드 표시 방식">
<div className="vtd-view-toggle">
<button
type="button"
className={`vtd-view-toggle-btn${viewMode === 'summary' ? ' vtd-view-toggle-btn--on' : ''}`}
onClick={() => onViewModeChange('summary')}
>
</button>
<button
type="button"
className={`vtd-view-toggle-btn${viewMode === 'detail' ? ' vtd-view-toggle-btn--on' : ''}`}
onClick={() => onViewModeChange('detail')}
>
</button>
</div>
</div>
{viewMode === 'detail' && (
<>
<span className="vtd-grid-head-divider" aria-hidden="true" />
<div className="vtd-grid-head-legend">
<span className="vtd-legend vtd-legend--match"> </span>
<span className="vtd-legend vtd-legend--pending"> </span>
<span className="vtd-legend vtd-legend--nomatch"> </span>
</div>
</>
)}
{session.running && (
<>
<span className="vtd-grid-head-divider" aria-hidden="true" />
<span className="vtd-grid-live"> 3</span>
</>
)}
</div>
)}
</div>
);
export default VirtualGridUnifiedHeader;