From b741181c97abc68b42da79497b21e6583df9f5e7 Mon Sep 17 00:00:00 2001 From: racgoo Date: Wed, 21 Aug 2024 18:32:32 +0900 Subject: [PATCH] =?UTF-8?q?fix(QA):=20QA=EB=82=B4=EC=9A=A9=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/admin/src/components/chat/Chat.tsx | 14 +++++- .../src/components/chat/RealTimeChatting.tsx | 2 +- .../components/error/CommonErrorBoundary.tsx | 44 +++++++++++++++++++ .../admin/src/hooks/socket/useChatSocket.ts | 12 ++--- packages/admin/src/hooks/useEvent.tsx | 29 +++++++----- packages/admin/src/layouts/appLayout.tsx | 19 ++++---- packages/admin/src/libs/index.tsx | 4 +- .../admin/src/pages/winner/WinnerResult.tsx | 14 ++++-- packages/admin/src/services/socket.ts | 2 +- packages/common/src/constants/socket.ts | 4 +- packages/user/src/services/socket.ts | 9 ++-- 11 files changed, 113 insertions(+), 40 deletions(-) create mode 100644 packages/admin/src/components/error/CommonErrorBoundary.tsx diff --git a/packages/admin/src/components/chat/Chat.tsx b/packages/admin/src/components/chat/Chat.tsx index 07a49212..6f0599f3 100644 --- a/packages/admin/src/components/chat/Chat.tsx +++ b/packages/admin/src/components/chat/Chat.tsx @@ -1,4 +1,4 @@ -import { BlockedChat, ChatProps, Message, Notice } from '@softeer/common/components'; +import { ChatProps, Message, Notice } from '@softeer/common/components'; import { FunctionComponent, useCallback } from 'react'; import { Button } from '../ui/button.js'; @@ -15,7 +15,17 @@ export default function Chat({ type, team, sender, content, id, onBlock }: Admin case 'n': return {content}; case 'b': - return ; + return ( + +
+
블록된 채팅: {content}
+
+
+ ); case 'm': default: return ( diff --git a/packages/admin/src/components/chat/RealTimeChatting.tsx b/packages/admin/src/components/chat/RealTimeChatting.tsx index ea3d9b82..99db92df 100644 --- a/packages/admin/src/components/chat/RealTimeChatting.tsx +++ b/packages/admin/src/components/chat/RealTimeChatting.tsx @@ -36,7 +36,7 @@ function RealTimeChatting({
공지사항 : {notice}
-
+
{messages.map((message) => ( diff --git a/packages/admin/src/components/error/CommonErrorBoundary.tsx b/packages/admin/src/components/error/CommonErrorBoundary.tsx new file mode 100644 index 00000000..bd205637 --- /dev/null +++ b/packages/admin/src/components/error/CommonErrorBoundary.tsx @@ -0,0 +1,44 @@ +import { ACCESS_TOKEN_KEY } from '@softeer/common/constants'; +import { Cookie } from '@softeer/common/utils'; +import { PropsWithChildren, useEffect } from 'react'; +import { ErrorBoundary } from 'react-error-boundary'; +import { useNavigate } from 'react-router-dom'; +import { Button } from '../ui/button.tsx'; + +export function CommonErrorFallback({ + error, + resetErrorBoundary, + }: { + error: Error, + resetErrorBoundary: () => void + }) { + const navigate = useNavigate(); + useEffect(() => { + switch (error.message) { + case '관리자 로그인을 먼저 진행해주세요': + case '로그인이 만료 되었습니다': + Cookie.clearCookie(ACCESS_TOKEN_KEY); + navigate('/'); + break; + default: + } + }, []); + + return ( +
+ {error.message} +
+ ); +} + +function CommonErrorBoundary({ children }: PropsWithChildren) { + return ( + { window.location.reload(); }} + > + {children} + + ); +} +export default CommonErrorBoundary; diff --git a/packages/admin/src/hooks/socket/useChatSocket.ts b/packages/admin/src/hooks/socket/useChatSocket.ts index 47175bc6..79798432 100644 --- a/packages/admin/src/hooks/socket/useChatSocket.ts +++ b/packages/admin/src/hooks/socket/useChatSocket.ts @@ -55,9 +55,11 @@ export default function useChatSocket() { [chatMessages], ); - const handleIncomingMessageHistory: SocketSubscribeCallbackType = useCallback( + const handleIncomingHistory: SocketSubscribeCallbackType = useCallback( (data: unknown) => { const parsedDataList = data as Omit[]; + const tmpNotice = parsedDataList.pop(); + setNotice(tmpNotice?.content ?? ''); setChatMessages((prevMessages) => [...parsedDataList, ...prevMessages] as ChatProps[]); }, [chatMessages], @@ -105,11 +107,11 @@ export default function useChatSocket() { [socketClient], ); - const handleRequestMessageHistory = useCallback(() => { + const handleRequestHistory = useCallback(() => { try { if (socketClient) { socketClient.sendMessages({ - destination: CHAT_SOCKET_ENDPOINTS.PUBLISH_MESSAGE_HISTORY, + destination: CHAT_SOCKET_ENDPOINTS.PUBLISH_HISTORY, body: {}, }); } else { @@ -125,10 +127,10 @@ export default function useChatSocket() { onReceiveMessage: handleIncomingMessage, onReceiveBlock: handleIncomintBlock, onReceiveNotice: handleIncomingNotice, - onReceiveMessageHistory: handleIncomingMessageHistory, + onReceiveMessageHistory: handleIncomingHistory, onBlock: handleBlock, onNotice: handleSendNotice, - onRequestMessageHistory: handleRequestMessageHistory, + onRequestMessageHistory: handleRequestHistory, messages: chatMessages, notice, isValid, diff --git a/packages/admin/src/hooks/useEvent.tsx b/packages/admin/src/hooks/useEvent.tsx index bff1f64e..c00f6514 100644 --- a/packages/admin/src/hooks/useEvent.tsx +++ b/packages/admin/src/hooks/useEvent.tsx @@ -1,5 +1,7 @@ -import { useMutation, useQuery } from '@tanstack/react-query'; +import { useMutation, useSuspenseQuery } from '@tanstack/react-query'; +import { useNavigate } from 'react-router-dom'; import { API, METHOD } from 'src/constants/api.ts'; +import RoutePaths from 'src/constants/routePath.ts'; import { CommonEvent, PersonalityTest, @@ -12,8 +14,9 @@ import fetchData from 'src/utils/fetchData.ts'; const useEvent = () => { const { openAlert } = useAlert(); + const navigate = useNavigate(); - const commonEventQuery = useQuery({ + const commonEventQuery = useSuspenseQuery({ queryFn: async () => { const response = await fetchData({ path: API.COMMON_EVENT, @@ -42,7 +45,7 @@ const useEvent = () => { commonEventMutation.mutate(commonEvent); }; - const quizEventQuery = useQuery({ + const quizEventQuery = useSuspenseQuery({ queryFn: async () => { const response = await fetchData({ path: API.QUIZ_LIST, @@ -53,7 +56,7 @@ const useEvent = () => { queryKey: [API.QUIZ_LIST], }); - const quizWinnerQuery = useQuery({ + const quizWinnerQuery = useSuspenseQuery({ queryFn: async () => { const response = await fetchData({ path: API.QUIZ_WINNER, @@ -88,7 +91,7 @@ const useEvent = () => { quizEventMutation.mutate(quizEvent); }; - const racingWinnerQuery = useQuery({ + const racingWinnerQuery = useSuspenseQuery({ queryFn: async () => { const response = await fetchData({ path: API.RACING_WINNERS, @@ -100,14 +103,16 @@ const useEvent = () => { }); const racingWinnerMutation = useMutation({ - mutationFn: async (winnerSettings: WinnerSetting[]) => - fetchData({ + mutationFn: async (winnerSettings: WinnerSetting[]) => { + const response = await fetchData({ path: API.RACING_WINNERS, method: METHOD.POST, payload: winnerSettings, - }), - onSuccess: () => { - racingWinnerQuery.refetch(); + }); + return response; + }, + onSettled: () => { + navigate(RoutePaths.WINNER_RESULT); }, onError: async (error) => { if (error.name !== 'SyntaxError') { @@ -120,7 +125,9 @@ const useEvent = () => { racingWinnerMutation.mutate(winnerSettings); }; - const personalityTestListQuery = useQuery({ + const personalityTestListQuery = useSuspenseQuery< + Response[API.PERSONALITY_TEST_LIST][METHOD.GET] + >({ queryFn: async () => { const response = await fetchData({ path: API.PERSONALITY_TEST_LIST, diff --git a/packages/admin/src/layouts/appLayout.tsx b/packages/admin/src/layouts/appLayout.tsx index 674a071d..3db46349 100644 --- a/packages/admin/src/layouts/appLayout.tsx +++ b/packages/admin/src/layouts/appLayout.tsx @@ -5,6 +5,7 @@ import { Outlet, useLocation, useNavigate } from 'react-router-dom'; import Header from 'src/components/appLayout/Header.tsx'; import SideBarContainer from 'src/components/appLayout/SideBarContainer.tsx'; import SystemContainer from 'src/components/appLayout/System.tsx'; +import CommonErrorBoundary from 'src/components/error/CommonErrorBoundary.tsx'; import { ErrorMessage } from 'src/constants/message.ts'; import RoutePaths from 'src/constants/routePath.ts'; import useHeader from 'src/hooks/useHeader.tsx'; @@ -32,15 +33,17 @@ export default function AppLayout() { }, [location.pathname]); return ( -
- {accessToken && } -
- -
-
- + +
+ {accessToken && } +
+ +
+
+ +
-
+ ); } diff --git a/packages/admin/src/libs/index.tsx b/packages/admin/src/libs/index.tsx index 59cd24a9..8b554868 100644 --- a/packages/admin/src/libs/index.tsx +++ b/packages/admin/src/libs/index.tsx @@ -7,7 +7,9 @@ export default function AppProviders({ children }: PropsWithChildren) { return ( - {children} + + {children} + ); diff --git a/packages/admin/src/pages/winner/WinnerResult.tsx b/packages/admin/src/pages/winner/WinnerResult.tsx index 06c28a26..b8fade57 100644 --- a/packages/admin/src/pages/winner/WinnerResult.tsx +++ b/packages/admin/src/pages/winner/WinnerResult.tsx @@ -16,14 +16,14 @@ const TabName = { const racingHeaders = [ { text: '당첨 등수', width: '20%' }, { text: '유저 이름', width: '20%' }, - { text: '유저 전화번호', width: '20%' }, + { text: '유저 이메일', width: '20%' }, { text: '공유 링크 접속 ', width: '20%' }, { text: '유형카드 ', width: '20%' }, ]; const quizHeaders = [ { text: '유저 이름', width: '33%' }, - { text: '유저 전화번호', width: '33%' }, + { text: '유저 이메일', width: '33%' }, { text: '당첨 날짜 ', width: '33%' }, ]; @@ -38,7 +38,7 @@ const getRows = (pageIndex: number, rawList: RacingWinner[] | QuizWinner[]) => { }; function WinnerResult() { - const { racingWinners, quizWinner } = useEvent(); + const { racingWinners, quizWinner, refechQuizEvent, refetchRacingWinners } = useEvent(); const { openAlert } = useAlert(); const [pageIndex, setPageIndex] = useState(0); @@ -52,6 +52,14 @@ function WinnerResult() { setRows(getRows(0, [])); }; + useEffect(() => { + if (tabName === TabName.QUIZ) { + refechQuizEvent(); + } else { + refetchRacingWinners(); + } + }, [tabName]); + useEffect(() => { if (tabName === TabName.QUIZ) { setHeaders(quizHeaders); diff --git a/packages/admin/src/services/socket.ts b/packages/admin/src/services/socket.ts index d485abda..2f1ecd03 100644 --- a/packages/admin/src/services/socket.ts +++ b/packages/admin/src/services/socket.ts @@ -100,7 +100,7 @@ class SocketManager { if (this.onReceiveMessageHistory) { this.socketClient.subscribe({ - destination: CHAT_SOCKET_ENDPOINTS.SUBSCRIBE_MESSAGE_HISTORY, + destination: CHAT_SOCKET_ENDPOINTS.SUBSCRIB_HISTORY, callback: this.onReceiveMessageHistory, }); } diff --git a/packages/common/src/constants/socket.ts b/packages/common/src/constants/socket.ts index 7484829a..4c759ac9 100644 --- a/packages/common/src/constants/socket.ts +++ b/packages/common/src/constants/socket.ts @@ -7,8 +7,8 @@ export const CHAT_SOCKET_ENDPOINTS = { PUBLISH_BLOCK: '/app/chat.sendBlock', SUBSCRIBE_NOTICE: '/topic/notice', PUBLISH_NOTICE: '/app/chat.sendNotice', - SUBSCRIBE_MESSAGE_HISTORY: '/user/queue/chatHistory', - PUBLISH_MESSAGE_HISTORY: '/app/chat.getHistory', + SUBSCRIB_HISTORY: '/user/queue/chatHistory', + PUBLISH_HISTORY: '/app/chat.getHistory', SUBSCRIBE_ERROR: '/user/queue/errors', } as const; diff --git a/packages/user/src/services/socket.ts b/packages/user/src/services/socket.ts index d7dd739f..c378616c 100644 --- a/packages/user/src/services/socket.ts +++ b/packages/user/src/services/socket.ts @@ -1,7 +1,4 @@ -import { - CHAT_SOCKET_ENDPOINTS, - RACING_SOCKET_ENDPOINTS, -} from '@softeer/common/constants'; +import { CHAT_SOCKET_ENDPOINTS, RACING_SOCKET_ENDPOINTS } from '@softeer/common/constants'; import { Socket, SocketSubscribeCallbackType } from '@softeer/common/utils'; import { SOCKET_BASE_URL } from 'src/constants/environments.ts'; import { toast } from 'src/hooks/useToast.ts'; @@ -79,11 +76,11 @@ class SocketManager { if (this.onReceiveChatList) { await this.socketClient.subscribe({ - destination: CHAT_SOCKET_ENDPOINTS.SUBSCRIBE_MESSAGE_HISTORY, + destination: CHAT_SOCKET_ENDPOINTS.SUBSCRIB_HISTORY, callback: this.onReceiveChatList, }); this.socketClient.sendMessages({ - destination: CHAT_SOCKET_ENDPOINTS.PUBLISH_MESSAGE_HISTORY, + destination: CHAT_SOCKET_ENDPOINTS.PUBLISH_HISTORY, body: {}, requiresAuth: false, });