전략편집기 팝업 기능 적용
This commit is contained in:
@@ -21,6 +21,7 @@ import { fetchEvaluationSnapshotAtBar } from '../utils/strategyEvaluationSnapsho
|
||||
import StrategyEvaluationSignalPanel from './strategyEvaluation/StrategyEvaluationSignalPanel';
|
||||
import StrategyEvaluationChart from './strategyEvaluation/StrategyEvaluationChart';
|
||||
import StrategyEvaluationSettingsTab from './strategyEvaluation/StrategyEvaluationSettingsTab';
|
||||
import StrategyEditorModal from './strategyEvaluation/StrategyEditorModal';
|
||||
import SePanelCollapseHandle from './strategyEditor/SePanelCollapseHandle';
|
||||
import { readStoredSize, readStoredBool, storeBool, storeSize, usePanelResize } from './strategyEditor/usePanelResize';
|
||||
import { getKoreanName } from '../utils/marketNameCache';
|
||||
@@ -75,6 +76,7 @@ export default function StrategyEvaluationPage({ theme = 'dark' }: Props) {
|
||||
const [paramsRevision, setParamsRevision] = useState(0);
|
||||
const [chartLoading, setChartLoading] = useState(false);
|
||||
const [backtestSignals, setBacktestSignals] = useState<BacktestSignal[]>([]);
|
||||
const [editorModalOpen, setEditorModalOpen] = useState(false);
|
||||
const evalSessionRef = useRef(0);
|
||||
const paramsRevisionRef = useRef(paramsRevision);
|
||||
|
||||
@@ -169,6 +171,27 @@ export default function StrategyEvaluationPage({ theme = 'dark' }: Props) {
|
||||
void loadStrategies().then(list => setStrategies(list ?? []));
|
||||
}, []);
|
||||
|
||||
const refreshStrategies = useCallback(async () => {
|
||||
const list = await loadStrategies();
|
||||
const next = list ?? [];
|
||||
setStrategies(next);
|
||||
if (selectedStrategyId == null) return;
|
||||
const still = next.find(s => s.id === selectedStrategyId);
|
||||
if (still) {
|
||||
setSelectedStrategy(hydrateStrategyDto(still));
|
||||
return;
|
||||
}
|
||||
setSelectedStrategyId(null);
|
||||
setSelectedStrategy(null);
|
||||
setAppliedIndicatorParams(null);
|
||||
setParamsRevision(v => v + 1);
|
||||
}, [selectedStrategyId]);
|
||||
|
||||
const handleCloseStrategyEditor = useCallback(() => {
|
||||
setEditorModalOpen(false);
|
||||
void refreshStrategies();
|
||||
}, [refreshStrategies]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedStrategyId) {
|
||||
setSelectedStrategy(null);
|
||||
@@ -308,26 +331,41 @@ export default function StrategyEvaluationPage({ theme = 'dark' }: Props) {
|
||||
>
|
||||
<aside className={`btd-sidebar seval-left-sidebar${leftOpen ? ' seval-left-sidebar--open' : ''}`}>
|
||||
<div className="btd-exec-list seval-left-panel">
|
||||
<div className="btd-exec-tabs" role="tablist">
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={leftTab === 'strategy'}
|
||||
className={`btd-exec-tab${leftTab === 'strategy' ? ' btd-exec-tab--on' : ''}`}
|
||||
onClick={() => setLeftTab('strategy')}
|
||||
>
|
||||
전략
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={leftTab === 'settings'}
|
||||
className={`btd-exec-tab${leftTab === 'settings' ? ' btd-exec-tab--on' : ''}`}
|
||||
onClick={() => setLeftTab('settings')}
|
||||
disabled={!selectedStrategy}
|
||||
>
|
||||
전략설정
|
||||
</button>
|
||||
<div className="seval-left-tabs-row">
|
||||
<div className="btd-exec-tabs" role="tablist">
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={leftTab === 'strategy'}
|
||||
className={`btd-exec-tab${leftTab === 'strategy' ? ' btd-exec-tab--on' : ''}`}
|
||||
onClick={() => setLeftTab('strategy')}
|
||||
>
|
||||
전략
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={leftTab === 'settings'}
|
||||
className={`btd-exec-tab${leftTab === 'settings' ? ' btd-exec-tab--on' : ''}`}
|
||||
onClick={() => setLeftTab('settings')}
|
||||
disabled={!selectedStrategy}
|
||||
>
|
||||
전략설정
|
||||
</button>
|
||||
</div>
|
||||
{leftTab === 'strategy' && (
|
||||
<button
|
||||
type="button"
|
||||
className="seval-strategy-add-btn"
|
||||
title="전략 추가·편집"
|
||||
aria-label="전략 추가·편집"
|
||||
onClick={() => setEditorModalOpen(true)}
|
||||
>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" aria-hidden>
|
||||
<path d="M12 5v14M5 12h14" strokeLinecap="round" />
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{leftTab === 'strategy' ? (
|
||||
@@ -487,6 +525,15 @@ export default function StrategyEvaluationPage({ theme = 'dark' }: Props) {
|
||||
</footer>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
{editorModalOpen && (
|
||||
<StrategyEditorModal
|
||||
theme={theme}
|
||||
initialStrategyId={selectedStrategyId}
|
||||
onClose={handleCloseStrategyEditor}
|
||||
onStrategiesChanged={() => { void refreshStrategies(); }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user