Files
web-page/src/pages/stock/screener/components/NodeCard.jsx

81 lines
2.7 KiB
JavaScript

import React from 'react';
export default function NodeCard({ meta, weight, params, onWeightChange, onParamsChange }) {
const enabled = (weight ?? 0) > 0;
return (
<div className="node-card" style={{ opacity: enabled ? 1 : 0.6 }}>
<div className="node-card-header">
<label style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<input
type="checkbox"
checked={enabled}
onChange={(e) => onWeightChange(e.target.checked ? (weight || 1) : 0)}
/>
<span>{meta.label}</span>
</label>
</div>
<div className="node-card-body">
<div className="weight-row">
<span style={{ width: 50, fontSize: 12, color: '#9ca3af' }}>가중치</span>
<input
type="range" min="0" max="3" step="0.1"
value={weight ?? 0}
disabled={!enabled}
onChange={(e) => onWeightChange(parseFloat(e.target.value))}
style={{ flex: 1 }}
/>
<span style={{ width: 32, textAlign: 'right', fontSize: 12 }}>{(weight ?? 0).toFixed(1)}</span>
</div>
{Object.entries(meta.param_schema?.properties || {}).map(([key, prop]) => (
<ParamRow
key={key}
paramKey={key}
prop={prop}
value={params?.[key] ?? meta.default_params?.[key]}
disabled={!enabled}
onChange={(v) => onParamsChange({ ...params, [key]: v })}
/>
))}
</div>
</div>
);
}
function ParamRow({ paramKey, prop, value, disabled, onChange }) {
const type = prop.type;
if (type === 'integer' || type === 'number') {
return (
<div className="param-row">
<span style={{ width: 100, fontSize: 12 }}>{paramKey}</span>
<input
type="number"
min={prop.minimum} max={prop.maximum}
step={type === 'integer' ? 1 : 0.1}
value={value ?? ''}
disabled={disabled}
onChange={(e) => onChange(type === 'integer' ? parseInt(e.target.value, 10) : parseFloat(e.target.value))}
style={{ width: 80 }}
/>
</div>
);
}
if (type === 'boolean') {
return (
<div className="param-row">
<label>
<input type="checkbox" checked={!!value} disabled={disabled}
onChange={(e) => onChange(e.target.checked)} />
<span style={{ marginLeft: 6, fontSize: 12 }}>{paramKey}</span>
</label>
</div>
);
}
// object/array는 MVP에서 read-only JSON 표시 (RsRating의 weights 등)
return (
<div className="param-row" style={{ fontSize: 11, color: '#9ca3af' }}>
{paramKey}: <code>{JSON.stringify(value)}</code>
</div>
);
}