Skip to content

Commit

Permalink
[FE] - 퀴즈 종료 시 라우팅 추가 및 퀴즈 랭킹 정보 소켓 연결 (#131)
Browse files Browse the repository at this point in the history
* feat: 제출순서 props 추가

* feat: submit answer response 콜백 추가

* feat: 퀴즈 랭킹 소켓 연결 추가

* feat: 퀴즈 종료 시 라우팅 및 소켓 이벤트 연결
  • Loading branch information
chan-byeong authored Nov 26, 2024
1 parent b9f4731 commit 8ec46c9
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 19 deletions.
2 changes: 2 additions & 0 deletions packages/client/src/app/routes/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import QnA from '@/pages/qna';
import GuestQnA from '@/pages/guest-qna';
import QuizList from '@/pages/quiz-list';
import QuizMasterSession from '@/pages/quiz-master-session';
import Leaderboard from '@/pages/leaderboard';

export default function Router() {
return (
Expand All @@ -31,6 +32,7 @@ export default function Router() {
</Route>
<Route path="/quiz/question" element={<QuizQuestion />} />
<Route path="/quiz/session/host/:pinCode/:id" element={<QuizMasterSession />} />
<Route path="/quiz/session/end" element={<Leaderboard />} />
<Route path={'*'} element={<NotFound />} />
</Routes>
);
Expand Down
3 changes: 3 additions & 0 deletions packages/client/src/pages/leaderboard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Leaderboard() {
return <div>Leaderboard</div>;
}
14 changes: 12 additions & 2 deletions packages/client/src/pages/quiz-master-session/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useParams } from 'react-router-dom';
import { useNavigate, useParams } from 'react-router-dom';
import { useEffect, useState } from 'react';

import { getCookie } from '@/shared/utils/cookie';
import { CustomButton } from '@/shared/ui/buttons';
import AnswerGraph from '@/pages/quiz-master-session/ui/AnswerChart';
import RecentSubmittedAnswers from './ui/RecentSubmittedAnswers';
Expand All @@ -19,12 +21,14 @@ import {

export default function QuizMasterSession() {
const { pinCode } = useParams();
const navigate = useNavigate();
const socket = getQuizSocket();
const [masterStatistics, setMasterStatistics] =
useState<MasterStatisticsResponse>(INITIAL_MASTER_STATISTICS);
const [quizData, setQuizData] = useState<QuizData>(INITIAL_QUIZ_DATA);
const [tick, setTick] = useState<TimerTickResponse>(INITIAL_TICK);
const [quizIndex, setQuizIndex] = useState(0);
const [isLastQuiz, setIsLastQuiz] = useState(false);

const initQuizData = () => {
setQuizData(INITIAL_QUIZ_DATA);
Expand All @@ -33,6 +37,11 @@ export default function QuizMasterSession() {
};

const handleNextQuiz = () => {
if (isLastQuiz) {
socket.emit('end quiz', { pinCode, sid: getCookie('sid') });
navigate('/quiz/session/end');
return;
}
initQuizData();
setQuizIndex((prev) => prev + 1);
socket.emit('show quiz', { pinCode });
Expand All @@ -42,8 +51,9 @@ export default function QuizMasterSession() {
socket.emit('show quiz', { pinCode });

const handleShowQuiz = (response: ShowQuizResponse) => {
const { currentQuizData } = response;
const { currentQuizData, isLast } = response;
setQuizData(currentQuizData);
setIsLastQuiz(isLast);
};
const handleMasterStatistics = (response: MasterStatisticsResponse) => {
setMasterStatistics(response);
Expand Down
13 changes: 10 additions & 3 deletions packages/client/src/pages/quiz-session/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';

import { getQuizSocket } from '@/shared/utils/socket';
import QuizBox from './ui/QuizBox';
import QuizEnd from './ui/QuizEnd';
import QuizHeader from './ui/QuizHeader';
import QuizLoading from './ui/QuizLoading';
import { toastController } from '@/features/toast/model/toastController';
// import { toastController } from '@/features/toast/model/toastController';
import { QuizData } from '@youquiz/shared/interfaces/utils/quizdata.interface';
import { ShowQuizResponse, TimerTickResponse } from '@youquiz/shared/interfaces/response';
import { INITIAL_QUIZ_DATA, INITIAL_TICK } from '@/shared/constants/initialState';

export default function QuizSession() {
const socket = getQuizSocket();
const toast = toastController();
// const toast = toastController();
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState(true);
const [isQuizEnd, setIsQuizEnd] = useState(false);
const [tick, setTick] = useState<TimerTickResponse>(INITIAL_TICK);
Expand Down Expand Up @@ -52,7 +54,7 @@ export default function QuizSession() {
setIsLoading(false);
})
.catch(() => {
toast.error('문제 로딩에 실패했습니다.');
// toast.error('문제 로딩에 실패했습니다.');
setIsLoading(false);
});

Expand All @@ -64,6 +66,11 @@ export default function QuizSession() {
setIsQuizEnd(true);
};

const handleQuizEnd = () => {
navigate('/quiz/session/end');
};

socket.on('end quiz', handleQuizEnd);
socket.on('timer tick', handleTick);
socket.on('time end', handleTimeEnd);

Expand Down
12 changes: 8 additions & 4 deletions packages/client/src/pages/quiz-session/ui/AfterQuizSubmit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@ import StatisticsGroup from '@/pages/quiz-master-session/ui/StatisticsGroup';
import { ParticipantStatisticsResponse } from '@youquiz/shared/interfaces/response';
interface AfterQuizSubmitProps {
participantStatistics: ParticipantStatisticsResponse;
submitOrder: number;
}

export default function AfterQuizSubmit({ participantStatistics }: AfterQuizSubmitProps) {
export default function AfterQuizSubmit({
participantStatistics,
submitOrder,
}: AfterQuizSubmitProps) {
return (
<div className="absolute top-0 z-10 p-6 w-full h-full mb-8 backdrop-blur-sm animate-[floatDown_1s_ease-in-out_forwards]">
<div className="max-w-4xl mx-auto bg-white rounded-2xl shadow-lg p-6">
<StatisticsGroup participantStatistics={participantStatistics} />
<div className="flex items-center justify-center">
<span className="text-xl font-semibold">나는 몇 등이지?</span>
<span></span>
<div className="flex flex-col items-center justify-center">
<span className="text-xl font-semibold">나는 몇 번째로 제출했을까?</span>
<span>{submitOrder}번째로 제출했습니다!</span>
</div>
</div>
</div>
Expand Down
24 changes: 17 additions & 7 deletions packages/client/src/pages/quiz-session/ui/QuizBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export default function QuizBox({ quiz, tick }: QuizBoxProps) {
const [participantStatistics, setParticipantStatistics] = useState<ParticipantStatisticsResponse>(
INITIAL_PARTICIPANT_STATISTICS,
);
const [submitOrder, setSubmitOrder] = useState<number>(0);

const easyButtonRef = useRef<HTMLButtonElement>(null);
const hardButtonRef = useRef<HTMLButtonElement>(null);
const socket = getQuizSocket();
Expand All @@ -40,12 +42,18 @@ export default function QuizBox({ quiz, tick }: QuizBoxProps) {
};

const handleSubmit = () => {
socket.emit('submit answer', {
selectedAnswer: selectedAnswer,
sid: getCookie('sid'),
pinCode: pinCode,
submitTime: tick.elapsedTime,
});
socket.emit(
'submit answer',
{
selectedAnswer: selectedAnswer,
sid: getCookie('sid'),
pinCode: pinCode,
submitTime: tick.elapsedTime,
},
(response: any) => {
setSubmitOrder(response.submitOrder);
},
);
setHasSubmitted(true);
};

Expand Down Expand Up @@ -166,7 +174,9 @@ export default function QuizBox({ quiz, tick }: QuizBoxProps) {
</button>
</div>
</div>
{hasSubmitted && <AfterQuizSubmit participantStatistics={participantStatistics} />}
{hasSubmitted && (
<AfterQuizSubmit participantStatistics={participantStatistics} submitOrder={submitOrder} />
)}
</>
);
}
26 changes: 23 additions & 3 deletions packages/client/src/pages/quiz-session/ui/QuizEnd.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
export default function QuizLoading() {
import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { getQuizSocket } from '@/shared/utils/socket';
import { getCookie } from '@/shared/utils/cookie';

export default function QuizEnd() {
const socket = getQuizSocket();
const { pinCode } = useParams();

const [ranking, setRanking] = useState<any>([]);

useEffect(() => {
socket.emit('show ranking', { pinCode, sid: getCookie('sid') }, (response: any) => {
setRanking(response);
});
}, []);

return (
<div className="min-h-screen bg-blue-100 p-4">
<div className="max-w-2xl mx-auto mt-12 p-16 ">
Expand All @@ -9,18 +25,22 @@ export default function QuizLoading() {
<div className="flex justify-center items-end gap-20 mb-12 border-2 bg-gradient-to-b from-blue-50 to-white rounded-2xl p-4">
<div className="flex flex-col items-center gap-2">
<div className="h-24 w-12 bg-gradient-to-t from-blue-200 to-blue-100 rounded-base" />
<div>{ranking.rankerDatas?.[1]?.nickname}</div>
</div>
<div className="flex flex-col items-center gap-2">
<div className="h-32 w-12 bg-gradient-to-t from-blue-300 to-blue-200 rounded-base" />
<div>{ranking.rankerDatas?.[0]?.nickname}</div>
</div>
<div className="flex flex-col items-center gap-2">
<div className="h-20 w-12 bg-gradient-to-t from-blue-100 to-blue-50 rounded-base" />
<div>{ranking.rankerDatas?.[2]?.nickname}</div>
</div>
</div>

<div className="flex flex-col justify-center items-center gap-8">
<span className="text-bold-xl">나는 몇 등?</span>
<span className="font-semibold text-4xl text-blue-600">#10</span>
<span className="text-semibold text-3xl">{ranking.myNickname}님은?</span>
<span className="font-semibold text-4xl text-blue-600">{ranking.myRank + 1}</span>
<span className="font-semibold text-2xl text-blue-600">{ranking.myScore}</span>
</div>
</div>
</div>
Expand Down

0 comments on commit 8ec46c9

Please sign in to comment.