추세검색 설정 추가

This commit is contained in:
Macbook
2026-05-27 01:36:06 +09:00
parent c1bcf88c6c
commit 2e08c6b16f
42 changed files with 1507 additions and 226 deletions
+15 -5
View File
@@ -65,12 +65,14 @@ interface MarketSearchPanelProps {
onAdd?: (market: string, meta: { koreanName: string; englishName: string }) => void;
/** 이미 추가된 종목 (add 모드에서 + 비활성) */
addedMarkets?: Set<string>;
/** 투자대상 최대 개수에 도달 — 미등록 종목 추가 불가 */
maxTargetsReached?: boolean;
}
export const MarketSearchPanel: React.FC<MarketSearchPanelProps> = ({
currentMarket, onSelect, onClose, anchorRect, anchorPlacement = 'slot', initialQuery = '',
variant = 'overlay', query: controlledQuery, onQueryChange,
actionMode = 'favorite', onAdd, addedMarkets,
actionMode = 'favorite', onAdd, addedMarkets, maxTargetsReached = false,
}) => {
const embedded = variant === 'embedded';
const [markets, setMarkets] = useState<MarketInfo[]>([]);
@@ -186,6 +188,7 @@ export const MarketSearchPanel: React.FC<MarketSearchPanelProps> = ({
if (embedded) onClose();
return;
}
if (maxTargetsReached) return;
const row = markets.find(m => m.market === market);
onAdd?.(market, {
koreanName: row?.korean_name ?? market,
@@ -196,7 +199,7 @@ export const MarketSearchPanel: React.FC<MarketSearchPanelProps> = ({
}
onSelect(market);
if (!embedded) onClose();
}, [actionMode, onSelect, onAdd, addedMarkets, markets, embedded, onClose]);
}, [actionMode, onSelect, onAdd, addedMarkets, maxTargetsReached, markets, embedded, onClose]);
const handleAddClick = useCallback((market: string, e: React.MouseEvent) => {
e.stopPropagation();
@@ -374,6 +377,7 @@ export const MarketSearchPanel: React.FC<MarketSearchPanelProps> = ({
const tk = tickers[m.market];
const isFav = favs.has(m.market);
const isAdded = addedMarkets?.has(m.market) ?? false;
const addBlocked = maxTargetsReached && !isAdded;
const isActive = m.market === currentMarket;
const rate = tk ? formatChangeRate(tk.signed_change_rate) : null;
const isUp = rate !== null && rate >= 0;
@@ -393,10 +397,16 @@ export const MarketSearchPanel: React.FC<MarketSearchPanelProps> = ({
actionMode === 'add' ? (
<button
type="button"
className={`msp-add-btn${isAdded ? ' msp-add-btn--done' : ''}`}
className={`msp-add-btn${isAdded ? ' msp-add-btn--done' : ''}${addBlocked ? ' msp-add-btn--blocked' : ''}`}
onClick={e => handleAddClick(m.market, e)}
disabled={isAdded}
title={isAdded ? '이미 추가됨' : '투자대상에 추가'}
disabled={isAdded || addBlocked}
title={
isAdded
? '이미 추가됨'
: addBlocked
? '투자대상 최대 개수에 도달했습니다'
: '투자대상에 추가'
}
>
{isAdded ? (
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">