diff --git a/apps/web/src/app/archive/wish/[id]/_hooks/useDeleteWish.ts b/apps/web/src/app/archive/wish/[id]/_hooks/useDeleteWish.ts index 45b9b7ef..0439bf51 100644 --- a/apps/web/src/app/archive/wish/[id]/_hooks/useDeleteWish.ts +++ b/apps/web/src/app/archive/wish/[id]/_hooks/useDeleteWish.ts @@ -4,7 +4,7 @@ import { toast } from 'sonner'; import { deleteWish } from '@/apis/deleteWish'; import { ROUTES } from '@/consts/route'; import { useBackWithFallback } from '@/hooks/useBackWithFallback'; -import { isGlobalNetError } from '@/utils/apiError'; +import { getApiErrorStatus, isGlobalNetError } from '@/utils/apiError'; import { getApiErrorMessage } from '@/utils/getApiErrorMessage'; /** 위시 단건 삭제 */ @@ -27,6 +27,8 @@ export const useDeleteWish = (wishId: number) => { * 404: 위시 존재하지 않음 */ toast.error(getApiErrorMessage(error)); + + if (getApiErrorStatus(error) === 404) backWithFallback(ROUTES.WISHLIST); }, }); diff --git a/apps/web/src/app/archive/wish/[id]/_hooks/usePatchWish.ts b/apps/web/src/app/archive/wish/[id]/_hooks/usePatchWish.ts index 5b7c6540..878b41b0 100644 --- a/apps/web/src/app/archive/wish/[id]/_hooks/usePatchWish.ts +++ b/apps/web/src/app/archive/wish/[id]/_hooks/usePatchWish.ts @@ -3,6 +3,7 @@ import { useRouter } from 'next/navigation'; import { toast } from 'sonner'; import { ROUTES } from '@/consts/route'; +import { useBackWithFallback } from '@/hooks/useBackWithFallback'; import { getApiErrorStatus, isGlobalNetError } from '@/utils/apiError'; import { getApiErrorMessage } from '@/utils/getApiErrorMessage'; @@ -11,6 +12,7 @@ import type { PatchWishRequestT } from '../_types/wish'; export const usePatchWish = (wishId: number) => { const router = useRouter(); + const backWithFallback = useBackWithFallback(); const queryClient = useQueryClient(); const { mutate: patchWishMutation, isPending: isPatchWishPending } = useMutation({ @@ -39,7 +41,7 @@ export const usePatchWish = (wishId: number) => { * 404: 위시 존재하지 않음 */ const status = getApiErrorStatus(error); - if (status === 403 || status === 404) router.replace(ROUTES.WISHLIST); + if (status === 403 || status === 404) backWithFallback(ROUTES.WISHLIST); }, }); diff --git a/apps/web/src/app/notification/_utils/getNotificationRoute.test.ts b/apps/web/src/app/notification/_utils/getNotificationRoute.test.ts index 14dd4425..236a1fe9 100644 --- a/apps/web/src/app/notification/_utils/getNotificationRoute.test.ts +++ b/apps/web/src/app/notification/_utils/getNotificationRoute.test.ts @@ -9,6 +9,7 @@ const ITEM_TYPES: NotificationTypeT[] = [ 'ITEM_PARSING_INCOMPLETE', 'ITEM_PARSING_FAILED', 'ITEM_PARSING_RECOVERED', + 'ITEM_PARSING_MERGED', 'ITEM_REFRESH_COMPLETED', ]; diff --git a/apps/web/src/app/notification/_utils/getNotificationRoute.ts b/apps/web/src/app/notification/_utils/getNotificationRoute.ts index 76f71ecd..11f4d976 100644 --- a/apps/web/src/app/notification/_utils/getNotificationRoute.ts +++ b/apps/web/src/app/notification/_utils/getNotificationRoute.ts @@ -20,6 +20,7 @@ export const getNotificationRoute = ( case 'ITEM_PARSING_INCOMPLETE': case 'ITEM_PARSING_FAILED': case 'ITEM_PARSING_RECOVERED': + case 'ITEM_PARSING_MERGED': case 'ITEM_REFRESH_COMPLETED': case 'ITEM_REFRESH_FAILED': if (extra?.kind === 'TOURNAMENT' && extra.tournamentId) { diff --git a/apps/web/src/hooks/useNotificationSSE.tsx b/apps/web/src/hooks/useNotificationSSE.tsx index d8bec0da..fc1c980a 100644 --- a/apps/web/src/hooks/useNotificationSSE.tsx +++ b/apps/web/src/hooks/useNotificationSSE.tsx @@ -215,6 +215,16 @@ export const useNotificationSSE = (enabled: boolean) => { case 'TOURNAMENT_ITEM_PARSED': queryClient.invalidateQueries({ queryKey: ['tournament', payload.tournamentId] }); break; + case 'TOURNAMENT_ITEM_MERGED': + queryClient.invalidateQueries({ queryKey: ['tournament', payload.tournamentId] }); + queryClient.invalidateQueries({ + queryKey: [ + 'tournamentItem', + payload.tournamentId, + payload.mergedIntoTournamentItemId, + ], + }); + break; case 'UNREAD_COUNT_CHANGED': void queryClient.refetchQueries({ queryKey: QUERY_KEYS.NOTIFICATION.LIST, @@ -254,6 +264,7 @@ export const useNotificationSSE = (enabled: boolean) => { case 'ITEM_REFRESH_COMPLETED': case 'ITEM_PARSING_COMPLETED': case 'ITEM_PARSING_RECOVERED': + case 'ITEM_PARSING_MERGED': if (payload.kind === 'TOURNAMENT' && payload.tournamentId != null) { queryClient.invalidateQueries({ queryKey: ['tournament', payload.tournamentId], diff --git a/apps/web/src/types/notification.ts b/apps/web/src/types/notification.ts index 30e1fb12..07bf0a8f 100644 --- a/apps/web/src/types/notification.ts +++ b/apps/web/src/types/notification.ts @@ -12,6 +12,7 @@ export type NotificationTypeT = | 'ITEM_PARSING_INCOMPLETE' | 'ITEM_PARSING_FAILED' | 'ITEM_PARSING_RECOVERED' + | 'ITEM_PARSING_MERGED' | 'ITEM_REFRESH_COMPLETED' | 'ITEM_REFRESH_FAILED' | 'ANNOUNCEMENT'; @@ -52,6 +53,12 @@ export type SilentSyncSsePayloadT = | (typeof ITEM_STATUS)['INCOMPLETE'] | (typeof ITEM_STATUS)['FAILED']; } + | { + type: 'TOURNAMENT_ITEM_MERGED'; + tournamentId: number; + tournamentItemId: number; + mergedIntoTournamentItemId: number; + } | { type: 'UNREAD_COUNT_CHANGED'; unreadCount: number; diff --git a/apps/web/src/utils/pushNotificationRoute.test.ts b/apps/web/src/utils/pushNotificationRoute.test.ts index 35b7c21f..76f83775 100644 --- a/apps/web/src/utils/pushNotificationRoute.test.ts +++ b/apps/web/src/utils/pushNotificationRoute.test.ts @@ -13,6 +13,7 @@ describe('getPushNotificationRoute', () => { { type: 'ITEM_PARSING_INCOMPLETE', refId: 4, kind: 'TOURNAMENT', tournamentId: 8 }, { type: 'ITEM_PARSING_FAILED', refId: 5, kind: 'TOURNAMENT', tournamentId: 9 }, { type: 'ITEM_PARSING_RECOVERED', refId: 6, kind: 'TOURNAMENT', tournamentId: 10 }, + { type: 'ITEM_PARSING_MERGED', refId: 9, kind: 'WISH' }, { type: 'ITEM_REFRESH_COMPLETED', refId: 7, kind: 'WISH' }, { type: 'ITEM_REFRESH_FAILED', refId: 8, kind: 'WISH' }, ]; diff --git a/apps/web/src/utils/pushNotificationRoute.ts b/apps/web/src/utils/pushNotificationRoute.ts index 1758c283..0fe7e1eb 100644 --- a/apps/web/src/utils/pushNotificationRoute.ts +++ b/apps/web/src/utils/pushNotificationRoute.ts @@ -11,6 +11,7 @@ export const getPushNotificationRoute = (payload: DeepLinkPayloadT) => { case PUSH_NOTIFICATION_TYPE.ITEM_PARSING_INCOMPLETE: case PUSH_NOTIFICATION_TYPE.ITEM_PARSING_FAILED: case PUSH_NOTIFICATION_TYPE.ITEM_PARSING_RECOVERED: + case PUSH_NOTIFICATION_TYPE.ITEM_PARSING_MERGED: case PUSH_NOTIFICATION_TYPE.ITEM_REFRESH_COMPLETED: case PUSH_NOTIFICATION_TYPE.ITEM_REFRESH_FAILED: if (payload.kind === 'TOURNAMENT' && payload.tournamentId) { diff --git a/packages/core/src/consts/webBridge.ts b/packages/core/src/consts/webBridge.ts index 5f88821c..eafeae51 100644 --- a/packages/core/src/consts/webBridge.ts +++ b/packages/core/src/consts/webBridge.ts @@ -66,6 +66,7 @@ export const PUSH_NOTIFICATION_TYPE = { ITEM_PARSING_INCOMPLETE: 'ITEM_PARSING_INCOMPLETE', ITEM_PARSING_FAILED: 'ITEM_PARSING_FAILED', ITEM_PARSING_RECOVERED: 'ITEM_PARSING_RECOVERED', + ITEM_PARSING_MERGED: 'ITEM_PARSING_MERGED', ITEM_REFRESH_COMPLETED: 'ITEM_REFRESH_COMPLETED', ITEM_REFRESH_FAILED: 'ITEM_REFRESH_FAILED', } as const; diff --git a/packages/core/src/types/pushNotification.ts b/packages/core/src/types/pushNotification.ts index af27a0ab..4b30e4a3 100644 --- a/packages/core/src/types/pushNotification.ts +++ b/packages/core/src/types/pushNotification.ts @@ -58,6 +58,7 @@ export type DeepLinkPayloadT = | 'ITEM_PARSING_INCOMPLETE' | 'ITEM_PARSING_FAILED' | 'ITEM_PARSING_RECOVERED' + | 'ITEM_PARSING_MERGED' | 'ITEM_REFRESH_COMPLETED' | 'ITEM_REFRESH_FAILED'; refId: number;