goldenChat base source add

This commit is contained in:
aidev
2026-05-23 15:11:48 +09:00
commit a4ea7762b5
2081 changed files with 1155760 additions and 0 deletions
+108
View File
@@ -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);
}