전략편집기 목록방식 오류 수정

This commit is contained in:
Macbook
2026-06-18 01:57:46 +09:00
parent ac55748aec
commit b96fc64c91
8 changed files with 371 additions and 70 deletions
@@ -32,6 +32,7 @@ import {
import StartTimeframeCheckboxes from './StartTimeframeCheckboxes';
import LogicGateOpToggle from './LogicGateOpToggle';
import { formatStartCandleTypesLabel } from '../../utils/strategyStartNodes';
import { START_NODE_ID } from '../../utils/strategyFlowLayout';
import { buildSidewaysFilterNode } from '../../utils/sidewaysFilterPaletteStorage';
import {
findPaletteDropKeyAtPoint,
@@ -293,7 +294,7 @@ interface StartSectionBlockProps {
def: DefType;
dragOverKey: string | null;
setDragOverKey: (key: string | null) => void;
onRootChange: (root: LogicNode | null) => void;
onRootChange: (root: LogicNode | null | ((prev: LogicNode | null) => LogicNode | null)) => void;
onCandleTypesChange: (candleTypes: string[]) => void;
onDeleteStart?: () => void;
onAddStart?: () => void;
@@ -324,16 +325,14 @@ function StartSectionBlock({
return;
}
const newNode = makeNode(data.type, data.value, signalTab, def, makeNodeOptionsFromPalette(data));
if (!root) {
onRootChange(newNode);
return;
}
if (!targetId) {
onRootChange(mergeAtRoot(root, newNode, data.type === 'operator'));
return;
}
onRootChange(addChild(root, targetId, newNode));
}, [root, signalTab, def, onRootChange, onAddStart]);
onRootChange(prev => {
if (!prev) return newNode;
if (!targetId) {
return mergeAtRoot(prev, newNode, data.type === 'operator');
}
return addChild(prev, targetId, newNode);
});
}, [signalTab, def, onRootChange, onAddStart]);
const handleSectionDrop = (e: React.DragEvent) => {
e.preventDefault();
@@ -408,7 +407,9 @@ interface Props {
editorState: EditorConditionState;
signalTab: 'buy' | 'sell';
def: DefType;
onEditorStateChange: (next: EditorConditionState) => void;
onEditorStateChange: (
next: EditorConditionState | ((prev: EditorConditionState) => EditorConditionState),
) => void;
onAddStart?: () => void;
onOrphansChange?: (nodes: LogicNode[]) => void;
orphans?: LogicNode[];
@@ -438,24 +439,35 @@ export default function StrategyListEditor({
onAddStart();
return;
}
onEditorStateChange(addExtraStartSection(editorState));
}, [onAddStart, onEditorStateChange, editorState]);
onEditorStateChange(prev => addExtraStartSection(prev));
}, [onAddStart, onEditorStateChange]);
const handleRootChange = useCallback((startId: string, root: LogicNode | null) => {
onEditorStateChange(updateBranchRoot(editorState, startId, root));
}, [editorState, onEditorStateChange]);
const handleRootChange = useCallback((
startId: string,
root: LogicNode | null | ((prev: LogicNode | null) => LogicNode | null),
) => {
onEditorStateChange(prev => {
const currentRoot = startId === START_NODE_ID
? prev.root
: (prev.extraRoots[startId] ?? null);
const resolved = typeof root === 'function' ? root(currentRoot) : root;
return updateBranchRoot(prev, startId, resolved);
});
}, [onEditorStateChange]);
const handleCandleTypesChange = useCallback((startId: string, candleTypes: string[]) => {
onEditorStateChange(updateStartCandleTypes(editorState, startId, candleTypes));
}, [editorState, onEditorStateChange]);
onEditorStateChange(prev => updateStartCandleTypes(prev, startId, candleTypes));
}, [onEditorStateChange]);
const handleDeleteStart = useCallback((startId: string) => {
const { state, orphanedNodes } = removeStartSection(editorState, startId);
onEditorStateChange(state);
if (orphanedNodes.length && onOrphansChange) {
onOrphansChange([...orphans, ...orphanedNodes]);
}
}, [editorState, onEditorStateChange, onOrphansChange, orphans]);
onEditorStateChange(prev => {
const { state, orphanedNodes } = removeStartSection(prev, startId);
if (orphanedNodes.length && onOrphansChange) {
onOrphansChange([...orphans, ...orphanedNodes]);
}
return state;
});
}, [onEditorStateChange, onOrphansChange, orphans]);
const resolvePaletteNode = useCallback((
data: { type: string; value: string; label: string; composite?: boolean },
@@ -487,26 +499,25 @@ export default function StrategyListEditor({
return;
}
const section = collectStartSections(editorState).find(s => s.startId === startId);
if (!section) return;
const newNode = resolvePaletteNode(data);
if (!newNode) return;
const root = section.root;
if (!root) {
handleRootChange(startId, newNode);
return;
}
if (!targetId) {
handleRootChange(startId, mergeAtRoot(root, newNode, data.type === 'operator'));
return;
}
handleRootChange(startId, addChild(root, targetId, newNode));
onEditorStateChange(prev => {
const section = collectStartSections(prev).find(s => s.startId === startId);
if (!section) return prev;
const root = section.root;
if (!root) {
return updateBranchRoot(prev, startId, newNode);
}
if (!targetId) {
return updateBranchRoot(prev, startId, mergeAtRoot(root, newNode, data.type === 'operator'));
}
return updateBranchRoot(prev, startId, addChild(root, targetId, newNode));
});
}, [
editorState,
handleAddStart,
handleRootChange,
onEditorStateChange,
resolvePaletteNode,
]);