/** * 전략 평가 — 우측 패널 전략지표 (전략편집기 지표 탭과 동일) */ import React, { useMemo, useState } from 'react'; import PaletteChip from '../strategyEditor/PaletteChip'; import IndicatorPaletteTab from '../strategyEditor/IndicatorPaletteTab'; import SidewaysFilterPaletteTab from '../strategyEditor/SidewaysFilterPaletteTab'; import { getIndicatorPeriodLabel } from '../../utils/strategyFlowLayout'; import { loadPaletteItems, type PaletteItem, } from '../../utils/strategyPaletteStorage'; import { loadSidewaysPaletteItems } from '../../utils/sidewaysFilterPaletteStorage'; import type { DefType } from '../../utils/strategyEditorShared'; import type { useStrategyEvaluationEditor } from '../../hooks/useStrategyEvaluationEditor'; type EditorApi = Pick< ReturnType, 'def' | 'applyPalette' | 'applyPaletteItem' | 'applySidewaysFilter' >; interface Props { editor: EditorApi; } const OPERATORS = [ { type: 'operator' as const, value: 'AND', label: 'AND', color: 'logic-and' }, { type: 'operator' as const, value: 'OR', label: 'OR', color: 'logic-or' }, { type: 'operator' as const, value: 'NOT', label: 'NOT', color: 'logic-not' }, ]; const MA_BAND_ITEMS = [ { type: 'indicator' as const, value: 'MA', label: 'MA', desc: '이동평균', color: 'band' }, { type: 'indicator' as const, value: 'EMA', label: 'EMA', desc: '지수이동평균', color: 'band' }, { type: 'indicator' as const, value: 'BOLLINGER', label: 'Bollinger', desc: '볼린저밴드', color: 'band' }, { type: 'indicator' as const, value: 'DONCHIAN', label: 'Donchian', desc: '돈치안 채널', color: 'band' }, { type: 'indicator' as const, value: 'ICHIMOKU', label: 'Ichimoku', desc: '일목균형표', color: 'band' }, ]; function paletteKey(type: string, id: string) { return `${type}:${id}`; } const StrategyEvaluationIndicatorPalettePanel: React.FC = ({ editor }) => { const { def, applyPalette, applyPaletteItem, applySidewaysFilter } = editor; const [paletteSearch, setPaletteSearch] = useState(''); const [indicatorSubTab, setIndicatorSubTab] = useState<'auxiliary' | 'composite' | 'range'>('auxiliary'); const [auxiliaryPalette, setAuxiliaryPalette] = useState(() => loadPaletteItems('auxiliary')); const [compositePalette, setCompositePalette] = useState(() => loadPaletteItems('composite')); const [sidewaysPalette, setSidewaysPalette] = useState(() => loadSidewaysPaletteItems()); const [selectedPaletteKey, setSelectedPaletteKey] = useState(null); const q = paletteSearch.trim().toLowerCase(); const match = (label: string, desc?: string) => !q || label.toLowerCase().includes(q) || (desc?.toLowerCase().includes(q) ?? false); const isPaletteSelected = (type: string, id: string) => selectedPaletteKey === paletteKey(type, id); const selectPalette = (type: string, id: string) => { setSelectedPaletteKey(paletteKey(type, id)); }; const filteredMaBand = useMemo( () => MA_BAND_ITEMS.filter(i => match(i.label, i.desc)), // eslint-disable-next-line react-hooks/exhaustive-deps [q], ); return (
setPaletteSearch(e.target.value)} />

시작 · 논리

setSelectedPaletteKey('start:START')} onAdd={() => applyPalette('start', 'START')} /> {OPERATORS.map(op => ( selectPalette(op.type, op.value)} onAdd={() => applyPalette(op.type, op.value)} /> ))}
{filteredMaBand.length > 0 && (

밴드 · 추세

{filteredMaBand.map(item => ( selectPalette(item.type, item.value)} onAdd={() => applyPalette(item.type, item.value)} /> ))}
)}
{indicatorSubTab === 'auxiliary' ? ( setSelectedPaletteKey(id ? paletteKey('auxiliary', id) : null)} onAddToCanvas={item => { selectPalette('auxiliary', item.id); applyPaletteItem(item); }} /> ) : indicatorSubTab === 'composite' ? ( setSelectedPaletteKey(id ? paletteKey('composite', id) : null)} onAddToCanvas={item => { selectPalette('composite', item.id); applyPaletteItem(item); }} /> ) : ( setSelectedPaletteKey(id ? paletteKey('range', id) : null)} onAddToCanvas={item => { selectPalette('range', item.id); applySidewaysFilter(item.id); }} /> )}
); }; export default StrategyEvaluationIndicatorPalettePanel;