124 lines
4.4 KiB
TypeScript
124 lines
4.4 KiB
TypeScript
import React, { useEffect, useRef } from 'react';
|
||
import type { ConditionDSL } from '../../utils/strategyTypes';
|
||
import type { DefType } from '../../utils/strategyEditorShared';
|
||
import {
|
||
getConditionRightPeriod,
|
||
getConditionThreshold,
|
||
getConditionValuePeriod,
|
||
getCompositePeriodPresetOptions,
|
||
getPeriodPresetOptions,
|
||
getThresholdBounds,
|
||
getThresholdPresetOptions,
|
||
hasEditableThreshold,
|
||
setConditionRightPeriod,
|
||
setConditionThreshold,
|
||
setConditionValuePeriod,
|
||
usesValuePeriodField,
|
||
} from '../../utils/conditionPeriods';
|
||
import { compositeDisplayName, compositeElementLabel } from '../../utils/compositeIndicators';
|
||
import ComboNumberInput from './ComboNumberInput';
|
||
|
||
interface Props {
|
||
condition: ConditionDSL;
|
||
def: DefType;
|
||
onChange: (c: ConditionDSL) => void;
|
||
onClose: () => void;
|
||
popoverClassName?: string;
|
||
}
|
||
|
||
export default function ConditionNodeSettings({
|
||
condition, def, onChange, onClose, popoverClassName = 'se-flow-settings-pop',
|
||
}: Props) {
|
||
const ref = useRef<HTMLDivElement>(null);
|
||
|
||
useEffect(() => {
|
||
const onDoc = (e: MouseEvent) => {
|
||
if (ref.current && !ref.current.contains(e.target as Node)) onClose();
|
||
};
|
||
document.addEventListener('mousedown', onDoc);
|
||
return () => document.removeEventListener('mousedown', onDoc);
|
||
}, [onClose]);
|
||
|
||
const rightThreshold = getConditionThreshold(condition, 'right');
|
||
const showThreshold = hasEditableThreshold(condition) && rightThreshold != null;
|
||
const periodPresets = getPeriodPresetOptions(condition.indicatorType, def);
|
||
const thresholdPresets = getThresholdPresetOptions(condition.indicatorType);
|
||
const thresholdBounds = getThresholdBounds(condition.indicatorType);
|
||
|
||
return (
|
||
<div
|
||
ref={ref}
|
||
className={popoverClassName}
|
||
role="dialog"
|
||
aria-label="지표 설정"
|
||
onClick={e => e.stopPropagation()}
|
||
>
|
||
<div className="se-flow-settings-head">
|
||
<span>지표 설정</span>
|
||
<button
|
||
type="button"
|
||
className="se-flow-settings-close"
|
||
aria-label="닫기"
|
||
title="닫기"
|
||
onClick={onClose}
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
{condition.composite ? (
|
||
<>
|
||
<label className="se-flow-settings-field">
|
||
<span>{compositeElementLabel(condition.indicatorType, 1)} 기준값 (기간, 일)</span>
|
||
<ComboNumberInput
|
||
key={`composite-left-${condition.indicatorType}-${getConditionValuePeriod(condition, def)}`}
|
||
value={getConditionValuePeriod(condition, def)}
|
||
options={getCompositePeriodPresetOptions(condition.indicatorType, def, 'left')}
|
||
min={1}
|
||
max={500}
|
||
onChange={p => onChange(setConditionValuePeriod(condition, p, def))}
|
||
/>
|
||
</label>
|
||
<label className="se-flow-settings-field">
|
||
<span>{compositeElementLabel(condition.indicatorType, 2)} 기준값 (기간, 일)</span>
|
||
<ComboNumberInput
|
||
key={`composite-right-${condition.indicatorType}-${getConditionRightPeriod(condition, def)}`}
|
||
value={getConditionRightPeriod(condition, def)}
|
||
options={getCompositePeriodPresetOptions(condition.indicatorType, def, 'right')}
|
||
min={1}
|
||
max={500}
|
||
onChange={p => onChange(setConditionRightPeriod(condition, p))}
|
||
/>
|
||
</label>
|
||
</>
|
||
) : usesValuePeriodField(condition) ? (
|
||
<label className="se-flow-settings-field">
|
||
<span>{condition.indicatorType} 기간 (일)</span>
|
||
<ComboNumberInput
|
||
value={getConditionValuePeriod(condition, def)}
|
||
options={periodPresets}
|
||
min={1}
|
||
max={500}
|
||
onChange={p => onChange(setConditionValuePeriod(condition, p, def))}
|
||
/>
|
||
</label>
|
||
) : null}
|
||
{showThreshold && rightThreshold != null && (
|
||
<label className="se-flow-settings-field">
|
||
<span>임계값</span>
|
||
<ComboNumberInput
|
||
value={rightThreshold}
|
||
options={thresholdPresets}
|
||
min={thresholdBounds.min}
|
||
max={thresholdBounds.max}
|
||
allowDecimal
|
||
onChange={v => onChange(setConditionThreshold(condition, 'right', v))}
|
||
/>
|
||
</label>
|
||
)}
|
||
{condition.composite && (
|
||
<p className="se-flow-settings-hint">{compositeDisplayName(condition.indicatorType)}</p>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|