실시간 차트 보조지표 탭 문제 수정

This commit is contained in:
Macbook
2026-05-28 01:26:53 +09:00
parent 4f6694b206
commit 98dfb3613c
19 changed files with 801 additions and 182 deletions
@@ -17,6 +17,7 @@ import {
import IndicatorSettingsListSearch from './IndicatorSettingsListSearch';
import IndicatorSettingsListRow from './IndicatorSettingsListRow';
import { MAIN_INDICATOR_TYPES } from '../utils/indicatorMainTab';
import { useIndicatorListOrder } from '../hooks/useIndicatorListOrder';
export interface IndicatorSaveUiState {
save: () => Promise<void>;
@@ -48,6 +49,8 @@ export interface IndicatorMainDefaultsPanelProps {
onSaveUiState?: (state: IndicatorSaveUiState | null) => void;
/** DB 로드 완료·저장 후 재로드 트리거 */
settingsRevision?: number;
/** 목록 순서 변경 시 차트 보조지표 순서 동기화 */
onListOrderChange?: (orderedTypes: string[]) => void;
}
const ALL_TYPES = getSettingsIndicatorTypes();
@@ -77,8 +80,12 @@ const IndicatorMainDefaultsPanel: React.FC<IndicatorMainDefaultsPanelProps> = ({
saveAllDefaults,
onSaveUiState,
settingsRevision = 0,
onListOrderChange,
}) => {
const onChartTypes = useMemo(() => new Set(chartIndicators.map(i => i.type)), [chartIndicators]);
const { listOrder, moveType } = useIndicatorListOrder(onListOrderChange);
const [draggingType, setDraggingType] = useState<string | null>(null);
const [dragOverType, setDragOverType] = useState<string | null>(null);
const [expandedTypes, setExpandedTypes] = useState<Set<string>>(() => new Set());
const [configs, setConfigs] = useState<Record<string, IndicatorConfig>>({});
const [baselineFp, setBaselineFp] = useState('');
@@ -97,14 +104,23 @@ const IndicatorMainDefaultsPanel: React.FC<IndicatorMainDefaultsPanelProps> = ({
reloadFromDb();
}, [reloadFromDb, settingsRevision]);
useEffect(() => {
const clearDrag = () => {
setDraggingType(null);
setDragOverType(null);
};
document.addEventListener('dragend', clearDrag);
return () => document.removeEventListener('dragend', clearDrag);
}, []);
const dirty = useMemo(
() => baselineFp !== '' && fingerprintMap(configs) !== baselineFp,
[configs, baselineFp],
);
const filtered = useMemo(
() => filterSettingsIndicatorTypes(ALL_TYPES, search),
[search],
() => filterSettingsIndicatorTypes(listOrder, search),
[listOrder, search],
);
const { main: filteredMain, other: filteredOther } = useMemo(
() => partitionFilteredTypes(filtered),
@@ -184,6 +200,8 @@ const IndicatorMainDefaultsPanel: React.FC<IndicatorMainDefaultsPanelProps> = ({
return () => onSaveUiState(null);
}, [onSaveUiState, handleSaveAll, dirty, saving, saveMessage]);
const canReorder = !search.trim();
const renderRows = (types: string[]) => types.map(type => {
const cfg = configs[type];
if (!cfg) return null;
@@ -195,6 +213,29 @@ const IndicatorMainDefaultsPanel: React.FC<IndicatorMainDefaultsPanelProps> = ({
enabled={onChartTypes.has(type)}
expanded={expandedTypes.has(type)}
variant="settings"
draggable={canReorder}
isDragOver={canReorder && dragOverType === type && draggingType !== type}
onDragHandleStart={e => {
setDraggingType(type);
e.dataTransfer.setData('text/indicator-type', type);
e.dataTransfer.effectAllowed = 'move';
}}
onDragOver={e => {
if (!draggingType || draggingType === type) return;
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
setDragOverType(type);
}}
onDragLeave={() => {
if (dragOverType === type) setDragOverType(null);
}}
onDrop={e => {
e.preventDefault();
const from = e.dataTransfer.getData('text/indicator-type') || draggingType;
if (from && from !== type) moveType(from, type, 'before');
setDraggingType(null);
setDragOverType(null);
}}
onToggleExpand={() => toggleExpand(type)}
onToggleEnabled={on => handleToggleChart(type, on)}
onChange={updated => handleConfigChange(type, updated)}
@@ -208,7 +249,8 @@ const IndicatorMainDefaultsPanel: React.FC<IndicatorMainDefaultsPanelProps> = ({
<div className="stg-ind-intro">
<p>
<strong>Main</strong> {MAIN_INDICATOR_TYPES.length} , .
· . · <strong> </strong> DB에 .
· . <strong></strong> , pane .
· <strong> </strong> DB에 .
</p>
<button type="button" className="stg-ind-reset-all" onClick={handleResetAll}>
@@ -218,7 +260,7 @@ const IndicatorMainDefaultsPanel: React.FC<IndicatorMainDefaultsPanelProps> = ({
<IndicatorSettingsListSearch
value={search}
onChange={setSearch}
totalCount={ALL_TYPES.length}
totalCount={listOrder.length}
filteredCount={filtered.length}
className="stg-ind-search-block"
/>