From 3cba93e4d8b757ad60381d88460e702e857b1c46 Mon Sep 17 00:00:00 2001 From: kanghaeun Date: Wed, 12 Aug 2026 16:42:08 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=A3=BC=EC=B5=9C=EC=9E=90=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=ED=86=A0=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EB=8B=B4?= =?UTF-8?q?=EA=B8=B0=20=ED=99=94=EB=A9=B4=EC=97=90=EC=84=9C=EB=A7=8C=20?= =?UTF-8?q?=EB=85=B8=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 바로가기 제거 --- apps/web/src/hooks/useNotificationSSE.ts | 51 +++++++++--------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/apps/web/src/hooks/useNotificationSSE.ts b/apps/web/src/hooks/useNotificationSSE.ts index b769c81d..62071d5e 100644 --- a/apps/web/src/hooks/useNotificationSSE.ts +++ b/apps/web/src/hooks/useNotificationSSE.ts @@ -2,12 +2,11 @@ import { fetchEventSource } from '@microsoft/fetch-event-source'; import { WEBBRIDGE_MESSAGE_TYPE } from '@piki/core'; import type { Query } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query'; -import { useRouter } from 'next/navigation'; +import { usePathname } from 'next/navigation'; import { useEffect, useRef } from 'react'; import { toast } from 'sonner'; import { ENDPOINTS } from '@/consts/api'; -import { QUERY_ACTION } from '@/consts/queryAction'; import { QUERY_KEYS } from '@/consts/queryKeys'; import { ROUTES } from '@/consts/route'; import { CLIENT_TYPE } from '@/consts/webBridge'; @@ -27,39 +26,23 @@ const isWishQueryOfItem = (query: Query, itemId: number) => query.queryKey[0] === 'wish' && (query.state.data as { item?: { id: number } } | undefined)?.item?.id === itemId; -const SCROLL_TO_LAST_QUERY = `${QUERY_ACTION.KEY}=${QUERY_ACTION.VALUE.SCROLL_TO_LAST}`; - const buildToastMessage = (payload: NotificationSsePayloadT) => payload.body ? `${payload.title} ${payload.body}` : payload.title; -const resolveDeepLink = (payload: NotificationSsePayloadT): string | null => { - const { type, refId, kind, tournamentId } = payload; - - switch (type) { - case 'TOURNAMENT_STARTED': - return ROUTES.TOURNAMENT_CREATE(refId); - case 'TOURNAMENT_JOINED': - case 'TOURNAMENT_ITEM_ADDED': - return `${ROUTES.TOURNAMENT_CREATE(refId)}?${SCROLL_TO_LAST_QUERY}`; - case 'ITEM_PARSING_COMPLETED': - case 'ITEM_PARSING_FAILED': - if (kind === 'TOURNAMENT' && tournamentId != null) { - return `${ROUTES.TOURNAMENT_CREATE(tournamentId)}?${SCROLL_TO_LAST_QUERY}`; - } - return ROUTES.WISHLIST; - default: - return null; - } -}; - export const useNotificationSSE = (enabled: boolean) => { - const router = useRouter(); + const pathname = usePathname(); const queryClient = useQueryClient(); const retryDelayRef = useRef(1_000); const abortRef = useRef(null); const hasConnectedRef = useRef(false); const authFailCountRef = useRef(0); + // 주최자 알림 토스트를 담기 화면에서만 노출하기 위해 최신 경로를 ref로 관리 + const pathnameRef = useRef(pathname); + useEffect(() => { + pathnameRef.current = pathname; + }, [pathname]); + useEffect(() => { if (!enabled) return; @@ -169,10 +152,6 @@ export const useNotificationSSE = (enabled: boolean) => { type: 'all', }); const message = buildToastMessage(payload); - const deepLink = resolveDeepLink(payload); - const action = deepLink - ? { label: '바로가기', onClick: () => router.push(deepLink) } - : void 0; switch (payload.type) { case 'ITEM_PARSING_COMPLETED': @@ -199,17 +178,23 @@ export const useNotificationSSE = (enabled: boolean) => { predicate: query => isWishQueryOfItem(query, payload.refId), }); } - toast.error(message, { action, duration: 5000 }); + toast.error(message, { duration: 5000 }); break; case 'TOURNAMENT_STARTED': + queryClient.invalidateQueries({ queryKey: ['tournament', payload.refId] }); + toast.info(message, { duration: 5000 }); + break; case 'TOURNAMENT_JOINED': case 'TOURNAMENT_ITEM_ADDED': case 'TOURNAMENT_ITEM_DELETED': queryClient.invalidateQueries({ queryKey: ['tournament', payload.refId] }); - toast.info(message, { action, duration: 5000 }); + + if (pathnameRef.current === ROUTES.TOURNAMENT_CREATE(payload.refId)) { + toast.info(message, { duration: 5000 }); + } break; default: - toast.info(message, { action, duration: 5000 }); + toast.info(message, { duration: 5000 }); } } catch { // malformed JSON — 무시 @@ -241,5 +226,5 @@ export const useNotificationSSE = (enabled: boolean) => { cancelled = true; abortRef.current?.abort(); }; - }, [enabled, router, queryClient]); + }, [enabled, queryClient]); };