From 16fc1e0d806d7b3ba53a587f2fdba39921896ea7 Mon Sep 17 00:00:00 2001 From: BHyeonKim Date: Thu, 5 Jun 2025 17:46:44 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EB=B0=98=EC=9D=91=ED=98=95=20?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/routes/trade.$ticker.tsx | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/app/routes/trade.$ticker.tsx b/src/app/routes/trade.$ticker.tsx index 1f05905..314e2f0 100644 --- a/src/app/routes/trade.$ticker.tsx +++ b/src/app/routes/trade.$ticker.tsx @@ -49,7 +49,7 @@ export default function TradeRouteComponent({ })); return ( -
+
)} -
-
+
+
- 실시간 체결 목록 - {coinInfo && } + 실시간 차트 + {coinInfo && ( + + )}
-
+
주문 하기 {isLoggedIn && coinInfo ? ( @@ -77,24 +79,22 @@ export default function TradeRouteComponent({ )}
-
+
실시간 호가 {coinInfo && }
-
+
- 가상화폐 리스트 - + 실시간 체결 목록 + {coinInfo && }
-
+
- 실시간 차트 - {coinInfo && ( - - )} + 가상화폐 리스트 +
From 2249668f992453b73f060c161bcca4dbc92b0ead Mon Sep 17 00:00:00 2001 From: caniro Date: Sat, 7 Jun 2025 22:04:57 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=EC=B2=B4=EA=B2=B0=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20=EC=8B=9C=20=EC=95=8C=EB=A6=BC=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/root.tsx | 7 +++ .../trade/hooks/useTradeNotification.tsx | 52 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/features/trade/hooks/useTradeNotification.tsx diff --git a/src/app/root.tsx b/src/app/root.tsx index 19755ac..ab64b0d 100644 --- a/src/app/root.tsx +++ b/src/app/root.tsx @@ -12,6 +12,7 @@ import type { Route } from './+types/root'; import './app.css'; import { Slide } from 'react-toastify'; +import useTradeNotification from '~/features/trade/hooks/useTradeNotification'; import StompProvider from './provider/StompProvider'; export const links: Route.LinksFunction = () => [ @@ -74,9 +75,15 @@ export function Layout({ children }: { children: React.ReactNode }) { ); } +function TradeNotificationHandler() { + useTradeNotification(); + return null; +} + export default function App() { return ( + (null); + + useEffect(() => { + const fetchUserInfo = async () => { + try { + const response = await userApi.getUserInfo(); + const { data } = await (response.json() as Promise); + setUserId(data.userId); + } catch (error) { + console.error('Failed to fetch user info:', error); + toast.error('사용자 정보를 가져오는데 실패했습니다.'); + } + }; + + fetchUserInfo(); + }, []); + + useEffect(() => { + if (!client || !connected || !userId) return; + + const subscription = client.subscribe( + `/topic/tradeNotification/${userId}`, + (message) => { + const parsedData = JSON.parse(message.body) as TradeNotification; + const tradeType = parsedData.type === 'ask' ? '매도' : '매수'; + const toastMessage = `${parsedData.ticker} ${tradeType} 체결 완료 - 가격: ${parsedData.price}, 수량: ${parsedData.size}`; + toast.success(toastMessage); + }, + ); + + return () => { + subscription.unsubscribe(); + }; + }, [client, connected, userId]); +}