Files
goldenChart/frontend/src/components/LiveSignalNotifier.tsx
T
2026-05-25 22:30:54 +09:00

81 lines
2.7 KiB
TypeScript

/**
* 실시간 전략 STOMP 구독 — 화면과 무관하게 동작, 시그널은 알림 Context로 전달
*/
import React, { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
import { useLiveStrategyMarkers, type LiveMarker } from '../hooks/useLiveStrategyMarkers';
import { useTradeNotification } from '../contexts/TradeNotificationContext';
export interface LiveSignalNotifierHandle {
clearMarkers: () => void;
}
interface Props {
markets: string[];
/** 종목별 평가 분봉 — STOMP 구독 경로 */
marketSubscriptions?: { market: string; candleType: string }[];
activeMarket: string;
enabled: boolean;
popupEnabled: boolean;
strategyId: number | undefined;
executionType: string;
strategyName: string | null;
strategyNameByMarket?: Record<string, string>;
executionTypeByMarket?: Record<string, string>;
onMarkersChange: (markers: LiveMarker[]) => void;
/** 차트 화면일 때만 마커를 차트에 반영 */
chartMarkersActive: boolean;
}
export const LiveSignalNotifier = forwardRef<LiveSignalNotifierHandle, Props>(function LiveSignalNotifier({
markets,
marketSubscriptions,
activeMarket,
enabled,
popupEnabled: _popupEnabled,
strategyName,
executionType,
strategyNameByMarket,
executionTypeByMarket,
onMarkersChange,
chartMarkersActive,
}, ref) {
const { addNotification, refreshHistory } = useTradeNotification();
const onMarkersRef = useRef(onMarkersChange);
onMarkersRef.current = onMarkersChange;
useEffect(() => {
if (!enabled || markets.length === 0) return;
const id = window.setInterval(() => { void refreshHistory(); }, 20_000);
return () => window.clearInterval(id);
}, [enabled, markets.length, refreshHistory]);
const { clearMarkers } = useLiveStrategyMarkers({
markets,
subscriptions: marketSubscriptions,
activeMarket,
enabled: enabled && markets.length > 0,
onMarkersChange: markers => {
if (chartMarkersActive) onMarkersRef.current(markers);
},
onSignal: (marker: LiveMarker) => {
addNotification({
market: marker.market,
signalType: marker.signal,
price: marker.price,
candleTime: marker.time,
strategyName: strategyNameByMarket?.[marker.market] ?? strategyName,
executionType: executionTypeByMarket?.[marker.market] ?? executionType,
candleType: marketSubscriptions?.find(s => s.market === marker.market)?.candleType ?? '1m',
});
// STOMP만 수신·DB 저장 누락 시 배지 동기화
window.setTimeout(() => { void refreshHistory(); }, 800);
},
});
useImperativeHandle(ref, () => ({ clearMarkers }), [clearMarkers]);
return null;
});
export default LiveSignalNotifier;