/** * 매매 시그널 알림 — 차트 전체화면 모달 * 알림 아이템에 이미 표시된 캔들+보조지표 차트를 전체 화면으로 확대 표시 */ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import type { Theme } from '../../types'; import type { TradeNotificationItem } from '../../contexts/TradeNotificationContext'; import type { StrategyDto } from '../../utils/backendApi'; import { loadStrategy } from '../../utils/backendApi'; import { buildStrategyChartIndicators, candleTypeToTimeframe } from '../../utils/strategyToChartIndicators'; import { useIndicatorSettings } from '../../hooks/useIndicatorSettings'; import { formatStrategyCandleLabel } from '../../utils/strategyStartNodes'; import TradeSignalMiniChart from './TradeSignalMiniChart'; import { TRADE_BUY_COLOR, TRADE_SELL_COLOR } from '../../utils/tradeSignalColors'; import { formatSignalTime } from '../../utils/tradeSignalDisplay'; import { formatUpbitKrwPrice } from '../../utils/safeFormat'; const MAX_INDICATOR_CARDS = 8; interface Props { item: TradeNotificationItem; theme: Theme; onClose: () => void; } const FullscreenChartModal: React.FC = ({ item, theme, onClose }) => { const { getParams, getVisualConfig } = useIndicatorSettings(); const [strategy, setStrategy] = useState(null); /* 전략 로딩 */ useEffect(() => { if (!item.strategyId) return; loadStrategy(item.strategyId) .then(s => setStrategy(s)) .catch(() => {}); }, [item.strategyId]); /* 보조지표 config */ const allIndicatorConfigs = useMemo(() => { if (!strategy) return []; const all = buildStrategyChartIndicators(strategy, getParams, getVisualConfig); return all.slice(0, MAX_INDICATOR_CARDS); }, [strategy, getParams, getVisualConfig]); const timeframe = candleTypeToTimeframe(item.candleType ?? '1m'); const isBuy = item.signalType === 'BUY'; const accentColor = isBuy ? TRADE_BUY_COLOR : TRADE_SELL_COLOR; const sym = item.market.replace(/^KRW-/, ''); const tfLabel = formatStrategyCandleLabel(item.candleType ?? '1m'); /* ESC 키로 닫기 */ const handleKeyDown = useCallback((e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }, [onClose]); useEffect(() => { document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); }, [handleKeyDown]); /* body 스크롤 막기 */ useEffect(() => { const prev = document.body.style.overflow; document.body.style.overflow = 'hidden'; return () => { document.body.style.overflow = prev; }; }, []); return (
e.stopPropagation()} > {/* 헤더 */}
{item.signalType} {sym} {tfLabel} ₩{formatUpbitKrwPrice(item.price)} {formatSignalTime(item.candleTime)}
{item.strategyName && ( {item.strategyName} )}
{/* 차트 바디 */}
); }; export default FullscreenChartModal;