import React, { useState } from 'react'; import { useAuth } from '../../contexts/AuthContext'; import { useAppSettings } from '../../hooks/useAppSettings'; import { useVirtualTradingCore } from '@frontend/hooks/useVirtualTradingCore'; import { resolveVirtualTargetStrategyId } from '@frontend/utils/virtualTargetStrategy'; import { useNavigation } from '../../contexts/NavigationContext'; import BottomSheet from '../../components/BottomSheet'; import SegmentedControl from '../../components/SegmentedControl'; import VirtualTargetListRow from './VirtualTargetListRow'; import VirtualFocusScreen from './VirtualFocusScreen'; import VirtualTradeScreen from './VirtualTradeScreen'; import VirtualHistoryScreen from './VirtualHistoryScreen'; import { MarketSearchPanel } from '@frontend/components/MarketSearchPanel'; export default function VirtualTradingScreen() { const { virtualNav, goVirtualList, goVirtualDetail, goVirtualTrade, goVirtualHistory, } = useNavigation(); const { sessionKey: settingsSessionKey, authUser, guestMode } = useAuth(); const { isLoaded: settingsLoaded } = useAppSettings(settingsSessionKey); const core = useVirtualTradingCore({ settingsSessionKey }); const { targets, session, strategies, summary, trades, loading, snapshots, liveStatusByMarket, handleStart, handleStop, handleRemoveTarget, handleTogglePin, handleGlobalStrategyChange, handleExecutionTypeChange, handlePositionModeChange, addTarget, reloadTargetsFromStorage, } = core; const [addSheetOpen, setAddSheetOpen] = useState(false); const pnlPct = summary?.totalReturnPct ?? 0; const liveConnected = Object.values(liveStatusByMarket).some(s => s === 'live' || s === 'connecting'); const market = virtualNav.market; const target = market ? targets.find(t => t.market === market) : undefined; if (virtualNav.view === 'detail' && market && target) { const sid = resolveVirtualTargetStrategyId(target, session.globalStrategyId); const snap = snapshots[`${market}:${sid ?? ''}`] ?? snapshots[market]; return ( goVirtualTrade(market, side)} onHistory={() => goVirtualHistory(market)} /> ); } if (virtualNav.view === 'trade' && market && virtualNav.tradeSide) { return ( ); } if (virtualNav.view === 'history' && market) { return ( ); } return (

가상매매

총 자산
₩{(summary?.totalAsset ?? 0).toLocaleString()}
수익률
= 0 ? 'text-green' : 'text-red'}`} style={{ fontSize: 22, fontWeight: 700 }}> {pnlPct >= 0 ? '+' : ''}{pnlPct.toFixed(2)}%
{!liveConnected && session.running && (
실시간 연결 끊김
)}
{!settingsLoaded || loading ? (
{!settingsLoaded ? '설정 동기화 중…' : '로딩 중…'}
) : targets.length === 0 ? (

투자 대상 없음

{guestMode ? (

게스트 모드입니다. 웹과 같은 목록을 보려면 동일 계정으로 로그인하세요.

) : (

웹({authUser?.username})과 동일 DB입니다. ↻ 동기화 또는 + 로 종목 추가

)}
) : (
{targets.map(t => { const strategyId = resolveVirtualTargetStrategyId(t, session.globalStrategyId); const snapKey = `${t.market}:${strategyId ?? ''}`; const snap = snapshots[snapKey] ?? snapshots[t.market]; return ( goVirtualDetail(t.market)} onTrade={side => goVirtualTrade(t.market, side)} onTogglePin={() => void handleTogglePin(t.market)} onRemove={() => handleRemoveTarget(t.market)} /> ); })}
)} setAddSheetOpen(false)} height="full">
{ addTarget(m); setAddSheetOpen(false); }} onClose={() => setAddSheetOpen(false)} />
); }