// 관심종목 — localStorage 기반. 로그인 없이 토스의 '내 종목' 느낌. // 단순 string[] 직렬화. 다중 탭 동기화는 'storage' 이벤트로 처리. const KEY = "stockchart.watchlist"; function read(): string[] { if (typeof window === "undefined") return []; try { const raw = window.localStorage.getItem(KEY); if (!raw) return []; const v = JSON.parse(raw); return Array.isArray(v) ? v.filter((s) => typeof s === "string") : []; } catch { return []; } } function write(codes: string[]) { if (typeof window === "undefined") return; window.localStorage.setItem(KEY, JSON.stringify(codes)); // 같은 탭은 storage 이벤트가 안 떠서 수동 dispatch. window.dispatchEvent(new CustomEvent("watchlist:change")); } export const watchlist = { get(): string[] { return read(); }, has(code: string): boolean { return read().includes(code); }, add(code: string): void { const cur = read(); if (cur.includes(code)) return; write([code, ...cur]); }, remove(code: string): void { const cur = read(); write(cur.filter((c) => c !== code)); }, toggle(code: string): boolean { const cur = read(); if (cur.includes(code)) { write(cur.filter((c) => c !== code)); return false; } write([code, ...cur]); return true; }, // 컴포넌트가 변경 구독. unsubscribe 함수 반환. subscribe(cb: () => void): () => void { if (typeof window === "undefined") return () => {}; const onStorage = (e: StorageEvent) => { if (e.key === KEY) cb(); }; const onCustom = () => cb(); window.addEventListener("storage", onStorage); window.addEventListener("watchlist:change", onCustom as EventListener); return () => { window.removeEventListener("storage", onStorage); window.removeEventListener("watchlist:change", onCustom as EventListener); }; }, };