|
| 1 | +import { useEffect, useState } from 'react'; |
| 2 | +import { toast } from 'react-toastify/unstyled'; |
| 3 | + |
| 4 | +import { useStompClient } from '~/app/provider/StompProvider'; |
| 5 | +import { api as userApi } from '~/entities/user'; |
| 6 | +import type { UserInfoResponse } from '~/entities/user/types/user.type'; |
| 7 | + |
| 8 | +type TradeNotification = { |
| 9 | + ticker: string; |
| 10 | + price: number; |
| 11 | + size: number; |
| 12 | + type: 'ask' | 'bid'; |
| 13 | + tradedTime: string; |
| 14 | +}; |
| 15 | + |
| 16 | +export default function useTradeNotification() { |
| 17 | + const { client, connected } = useStompClient(); |
| 18 | + const [userId, setUserId] = useState<number | null>(null); |
| 19 | + |
| 20 | + useEffect(() => { |
| 21 | + const fetchUserInfo = async () => { |
| 22 | + try { |
| 23 | + const response = await userApi.getUserInfo(); |
| 24 | + const { data } = await (response.json() as Promise<UserInfoResponse>); |
| 25 | + setUserId(data.userId); |
| 26 | + } catch (error) { |
| 27 | + console.error('Failed to fetch user info:', error); |
| 28 | + toast.error('사용자 정보를 가져오는데 실패했습니다.'); |
| 29 | + } |
| 30 | + }; |
| 31 | + |
| 32 | + fetchUserInfo(); |
| 33 | + }, []); |
| 34 | + |
| 35 | + useEffect(() => { |
| 36 | + if (!client || !connected || !userId) return; |
| 37 | + |
| 38 | + const subscription = client.subscribe( |
| 39 | + `/topic/tradeNotification/${userId}`, |
| 40 | + (message) => { |
| 41 | + const parsedData = JSON.parse(message.body) as TradeNotification; |
| 42 | + const tradeType = parsedData.type === 'ask' ? '매도' : '매수'; |
| 43 | + const toastMessage = `${parsedData.ticker} ${tradeType} 체결 완료 - 가격: ${parsedData.price}, 수량: ${parsedData.size}`; |
| 44 | + toast.success(toastMessage); |
| 45 | + }, |
| 46 | + ); |
| 47 | + |
| 48 | + return () => { |
| 49 | + subscription.unsubscribe(); |
| 50 | + }; |
| 51 | + }, [client, connected, userId]); |
| 52 | +} |
0 commit comments