120 lines
3.0 KiB
TypeScript
120 lines
3.0 KiB
TypeScript
/**
|
|
* START 노드 — 평가 시간봉 다중 선택 (마감봉마다 독립 체크)
|
|
*/
|
|
import React from 'react';
|
|
import {
|
|
START_TIMEFRAME_GRAPH_ROWS,
|
|
STRATEGY_CANDLE_TYPE_OPTIONS,
|
|
STRATEGY_CANDLE_TYPES,
|
|
formatStrategyCandleLabel,
|
|
type StrategyCandleType,
|
|
} from '../../utils/strategyStartNodes';
|
|
|
|
interface Props {
|
|
selected: string[];
|
|
onChange: (next: string[]) => void;
|
|
className?: string;
|
|
/** 그래프 START: 2행 고정 배치 + 값 라벨(1m…) */
|
|
layout?: 'default' | 'graph';
|
|
compact?: boolean;
|
|
}
|
|
|
|
const OPTIONS_BY_VALUE = Object.fromEntries(
|
|
STRATEGY_CANDLE_TYPE_OPTIONS.map(o => [o.value, o]),
|
|
) as Record<StrategyCandleType, { value: string; label: string }>;
|
|
|
|
function CheckItem({
|
|
value,
|
|
checked,
|
|
showShortLabel,
|
|
onToggle,
|
|
}: {
|
|
value: StrategyCandleType;
|
|
checked: boolean;
|
|
showShortLabel: boolean;
|
|
onToggle: (value: string, checked: boolean) => void;
|
|
}) {
|
|
const opt = OPTIONS_BY_VALUE[value];
|
|
return (
|
|
<label className="se-start-tf-check" title={formatStrategyCandleLabel(value)}>
|
|
<input
|
|
type="checkbox"
|
|
checked={checked}
|
|
onChange={e => onToggle(value, e.target.checked)}
|
|
/>
|
|
<span>{showShortLabel ? value : opt.label}</span>
|
|
</label>
|
|
);
|
|
}
|
|
|
|
const StartTimeframeCheckboxes: React.FC<Props> = ({
|
|
selected,
|
|
onChange,
|
|
className = '',
|
|
layout = 'default',
|
|
compact = false,
|
|
}) => {
|
|
const selectedSet = new Set(selected);
|
|
|
|
const toggle = (value: string, checked: boolean) => {
|
|
if (checked) {
|
|
if (!selectedSet.has(value)) onChange([...selected, value]);
|
|
return;
|
|
}
|
|
const next = selected.filter(t => t !== value);
|
|
onChange(next.length > 0 ? next : [value]);
|
|
};
|
|
|
|
const stop = (e: React.SyntheticEvent) => e.stopPropagation();
|
|
|
|
if (layout === 'graph') {
|
|
return (
|
|
<div
|
|
className={`se-start-tf-checks se-start-tf-checks--graph${className ? ` ${className}` : ''}`}
|
|
role="group"
|
|
aria-label="조건 판별 시간봉"
|
|
onPointerDown={stop}
|
|
onMouseDown={stop}
|
|
onClick={stop}
|
|
>
|
|
{START_TIMEFRAME_GRAPH_ROWS.map((row, rowIdx) => (
|
|
<div key={rowIdx} className="se-start-tf-checks-row">
|
|
{row.map(ct => (
|
|
<CheckItem
|
|
key={ct}
|
|
value={ct}
|
|
checked={selectedSet.has(ct)}
|
|
showShortLabel
|
|
onToggle={toggle}
|
|
/>
|
|
))}
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className={`se-start-tf-checks${compact ? ' se-start-tf-checks--compact' : ''}${className ? ` ${className}` : ''}`}
|
|
role="group"
|
|
aria-label="조건 판별 시간봉"
|
|
onPointerDown={stop}
|
|
onMouseDown={stop}
|
|
onClick={stop}
|
|
>
|
|
{STRATEGY_CANDLE_TYPES.map(ct => (
|
|
<CheckItem
|
|
key={ct}
|
|
value={ct}
|
|
checked={selectedSet.has(ct)}
|
|
showShortLabel={compact}
|
|
onToggle={toggle}
|
|
/>
|
|
))}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default StartTimeframeCheckboxes;
|