goldenChat base source add
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* 관심종목(즐겨찾기) / 보유종목 관리
|
||||
* - DB(gc_watchlist)가 기준 저장소
|
||||
* - localStorage(gc_favorites)는 오프라인 미러·UI 동기화용
|
||||
*/
|
||||
|
||||
import { addWatchlistItem, removeWatchlistItem } from './backendApi';
|
||||
|
||||
const FAV_KEY = 'gc_favorites';
|
||||
const LEGACY_FAV_KEY = 'upbit_market_favorites';
|
||||
const HOLD_KEY = 'gc_holdings';
|
||||
|
||||
/** 관심종목 변경 시 MarketSearchPanel·App 등이 동기화하도록 발행 */
|
||||
export const FAVORITES_CHANGED_EVENT = 'gc-favorites-changed';
|
||||
|
||||
// ── 즐겨찾기 (관심종목) ─────────────────────────────────────────────────────
|
||||
|
||||
/** 구버전 MarketSearchPanel 키 → gc_favorites 로 1회 마이그레이션 */
|
||||
function migrateLegacyFavorites(): void {
|
||||
try {
|
||||
const raw = localStorage.getItem(FAV_KEY);
|
||||
if (raw) {
|
||||
const current = JSON.parse(raw) as string[];
|
||||
if (Array.isArray(current) && current.length > 0) return;
|
||||
}
|
||||
const legacy = localStorage.getItem(LEGACY_FAV_KEY);
|
||||
if (!legacy) return;
|
||||
const parsed = JSON.parse(legacy) as string[];
|
||||
if (Array.isArray(parsed) && parsed.length > 0) {
|
||||
saveFavorites(parsed, false);
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
export function getFavorites(): string[] {
|
||||
migrateLegacyFavorites();
|
||||
try { return JSON.parse(localStorage.getItem(FAV_KEY) ?? '[]'); }
|
||||
catch { return []; }
|
||||
}
|
||||
|
||||
export function saveFavorites(markets: string[], notify = true): void {
|
||||
try {
|
||||
localStorage.setItem(FAV_KEY, JSON.stringify(markets));
|
||||
if (notify) {
|
||||
window.dispatchEvent(new CustomEvent(FAVORITES_CHANGED_EVENT, { detail: markets }));
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
/**
|
||||
* 관심종목 토글 — DB 저장 + 실시간 전략 체크 대상 자동 연동(백엔드).
|
||||
* @returns 변경 후 관심종목 코드 목록
|
||||
*/
|
||||
export async function toggleFavorite(
|
||||
market: string,
|
||||
meta?: { koreanName?: string; englishName?: string },
|
||||
): Promise<string[]> {
|
||||
const list = getFavorites();
|
||||
let next: string[];
|
||||
if (list.includes(market)) {
|
||||
await removeWatchlistItem(market);
|
||||
next = list.filter(m => m !== market);
|
||||
} else {
|
||||
await addWatchlistItem({
|
||||
symbol: market,
|
||||
koreanName: meta?.koreanName,
|
||||
englishName: meta?.englishName,
|
||||
});
|
||||
next = [...list, market];
|
||||
}
|
||||
saveFavorites(next);
|
||||
return next;
|
||||
}
|
||||
|
||||
export function isFavorite(market: string): boolean {
|
||||
return getFavorites().includes(market);
|
||||
}
|
||||
|
||||
// ── 보유종목 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
export function getHoldings(): string[] {
|
||||
try { return JSON.parse(localStorage.getItem(HOLD_KEY) ?? '[]'); }
|
||||
catch { return []; }
|
||||
}
|
||||
|
||||
export function saveHoldings(markets: string[]): void {
|
||||
try { localStorage.setItem(HOLD_KEY, JSON.stringify(markets)); } catch { /* ignore */ }
|
||||
}
|
||||
|
||||
/** 추가 → 변경 후 전체 목록 반환 (중복 무시) */
|
||||
export function addHolding(market: string): string[] {
|
||||
const list = getHoldings();
|
||||
if (list.includes(market)) return list;
|
||||
const next = [...list, market];
|
||||
saveHoldings(next);
|
||||
return next;
|
||||
}
|
||||
|
||||
/** 제거 → 변경 후 전체 목록 반환 */
|
||||
export function removeHolding(market: string): string[] {
|
||||
const next = getHoldings().filter(m => m !== market);
|
||||
saveHoldings(next);
|
||||
return next;
|
||||
}
|
||||
|
||||
export function isHolding(market: string): boolean {
|
||||
return getHoldings().includes(market);
|
||||
}
|
||||
Reference in New Issue
Block a user