추세검색 설정 추가
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import {
|
||||
loadVirtualTargets,
|
||||
VIRTUAL_SESSION_CHANGED_EVENT,
|
||||
} from '../utils/virtualTradingStorage';
|
||||
import {
|
||||
addVirtualTarget,
|
||||
removeVirtualTarget,
|
||||
type VirtualTargetMeta,
|
||||
} from '../utils/virtualTargetMutations';
|
||||
import { getVirtualTargetMaxCount } from './useAppSettings';
|
||||
import { virtualTargetLimitMessage } from '../utils/virtualTargetLimits';
|
||||
|
||||
/** 가상투자 투자대상 마켓 집합 (추세검색 카드 등) */
|
||||
export function useVirtualTargetRegistry() {
|
||||
const [targets, setTargets] = useState(() => loadVirtualTargets());
|
||||
const [busyMarket, setBusyMarket] = useState<string | null>(null);
|
||||
|
||||
const refresh = useCallback(() => {
|
||||
setTargets(loadVirtualTargets());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
refresh();
|
||||
const onChange = () => refresh();
|
||||
window.addEventListener(VIRTUAL_SESSION_CHANGED_EVENT, onChange);
|
||||
return () => window.removeEventListener(VIRTUAL_SESSION_CHANGED_EVENT, onChange);
|
||||
}, [refresh]);
|
||||
|
||||
const addedSet = useMemo(
|
||||
() => new Set(targets.map(t => t.market)),
|
||||
[targets],
|
||||
);
|
||||
|
||||
const isInTargets = useCallback(
|
||||
(market: string) => addedSet.has(market),
|
||||
[addedSet],
|
||||
);
|
||||
|
||||
const isPinned = useCallback(
|
||||
(market: string) => targets.find(t => t.market === market)?.pinned === true,
|
||||
[targets],
|
||||
);
|
||||
|
||||
const add = useCallback(async (market: string, meta?: VirtualTargetMeta) => {
|
||||
if (addedSet.has(market) || busyMarket === market) return;
|
||||
const maxCount = getVirtualTargetMaxCount();
|
||||
if (targets.length >= maxCount) {
|
||||
window.alert(virtualTargetLimitMessage(maxCount));
|
||||
return;
|
||||
}
|
||||
setBusyMarket(market);
|
||||
try {
|
||||
const next = await addVirtualTarget(market, meta);
|
||||
setTargets(next);
|
||||
} catch (e) {
|
||||
console.warn('[VirtualTarget] add failed', market, e);
|
||||
window.alert('투자대상 추가에 실패했습니다.');
|
||||
} finally {
|
||||
setBusyMarket(null);
|
||||
}
|
||||
}, [addedSet, busyMarket, targets]);
|
||||
|
||||
const remove = useCallback(async (market: string) => {
|
||||
if (!addedSet.has(market) || busyMarket === market) return;
|
||||
if (targets.find(t => t.market === market)?.pinned) {
|
||||
window.alert('고정된 종목은 투자대상에서 삭제할 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
setBusyMarket(market);
|
||||
try {
|
||||
const next = await removeVirtualTarget(market);
|
||||
setTargets(next);
|
||||
} catch (e) {
|
||||
console.warn('[VirtualTarget] remove failed', market, e);
|
||||
window.alert('투자대상 제거에 실패했습니다.');
|
||||
} finally {
|
||||
setBusyMarket(null);
|
||||
}
|
||||
}, [addedSet, busyMarket, targets]);
|
||||
|
||||
return {
|
||||
addedSet,
|
||||
isInTargets,
|
||||
isPinned,
|
||||
add,
|
||||
remove,
|
||||
busyMarket,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user