Skip to content

Commit 2b28f25

Browse files
authored
Merge pull request #23 from CleanEngine/feat/trade-notify
feat: 체결 완료 시 알림 기능 추가
2 parents 2b67f5f + 0787dc0 commit 2b28f25

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

src/app/root.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type { Route } from './+types/root';
1212

1313
import './app.css';
1414
import { Slide } from 'react-toastify';
15+
import useTradeNotification from '~/features/trade/hooks/useTradeNotification';
1516
import StompProvider from './provider/StompProvider';
1617
import UserIdProvider from './provider/UserInfoProvider';
1718

@@ -75,6 +76,11 @@ export function Layout({ children }: { children: React.ReactNode }) {
7576
);
7677
}
7778

79+
function TradeNotificationHandler() {
80+
useTradeNotification();
81+
return null;
82+
}
83+
7884
export default function App() {
7985
return (
8086
<UserIdProvider>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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

Comments
 (0)