/** 지표 추가 팝업 — 사용자 정의 탭 (localStorage) */ export interface IndicatorCustomTab { id: string; name: string; /** INDICATOR_REGISTRY type 목록 (표시 순서) */ indicatorTypes: string[]; } const STORAGE_KEY = 'gc-indicator-custom-tabs-v1'; function newId(): string { return `tab-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`; } export function loadCustomTabs(): IndicatorCustomTab[] { try { const raw = localStorage.getItem(STORAGE_KEY); if (!raw) return []; const arr = JSON.parse(raw) as unknown; if (!Array.isArray(arr)) return []; return arr.filter( (t): t is IndicatorCustomTab => t != null && typeof t === 'object' && typeof (t as IndicatorCustomTab).id === 'string' && typeof (t as IndicatorCustomTab).name === 'string' && Array.isArray((t as IndicatorCustomTab).indicatorTypes), ); } catch { return []; } } export function saveCustomTabs(tabs: IndicatorCustomTab[]): void { localStorage.setItem(STORAGE_KEY, JSON.stringify(tabs)); window.dispatchEvent(new CustomEvent('gc-indicator-custom-tabs-changed')); } export function createCustomTab(name: string, indicatorTypes: string[]): IndicatorCustomTab { const tab: IndicatorCustomTab = { id: newId(), name: name.trim(), indicatorTypes: [...new Set(indicatorTypes)], }; const tabs = loadCustomTabs(); tabs.push(tab); saveCustomTabs(tabs); return tab; } export function updateCustomTab( id: string, patch: Partial>, ): IndicatorCustomTab | null { const tabs = loadCustomTabs(); const idx = tabs.findIndex(t => t.id === id); if (idx < 0) return null; const next: IndicatorCustomTab = { ...tabs[idx], ...patch, name: patch.name != null ? patch.name.trim() : tabs[idx].name, indicatorTypes: patch.indicatorTypes != null ? [...new Set(patch.indicatorTypes)] : tabs[idx].indicatorTypes, }; tabs[idx] = next; saveCustomTabs(tabs); return next; } export function deleteCustomTab(id: string): void { saveCustomTabs(loadCustomTabs().filter(t => t.id !== id)); }