Skip to content

Commit

Permalink
[FE - #109 ] Quiz-Session 소켓 연결 및 리팩토링 (#110)
Browse files Browse the repository at this point in the history
* feat: quiz-session socket 연결

* fix: socket transports 방식 websocket으로 고정

* feat: User Type 식별 및 퀴즈 시작 소켓 연결

* fix: 퀴즈 로딩 화면 UI 수정

* fix: quizLoading UI 변경

* feat: spin keyframe 추가

* feat: quiz loading UI 추가

* feat: quiz end UI 추가

* feat: quiz end 상태 추가

* feat: master-session 이벤트 추가

* fix: show quiz 응답 수정

* temp: 소켓 테스트를 위한 소켓 응답 코드 추가

* fix: user type fetch function added

* fix: Loading 페이지 Heigth 수정

* feat: Animation keyframe 추가

- floatDown : 아래로 내려오는 애니메이션
- swing : 좌우로 왔다갔다 하는 애니메이션

* fix: Quiz Session 소켓 로직 수정

* fix: QuizBox 소켓 로직 수정 및 Background 추가

* feat: tick props 추가
  • Loading branch information
chan-byeong authored Nov 24, 2024
1 parent a5a5b1f commit 72755f3
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 38 deletions.
36 changes: 17 additions & 19 deletions packages/client/src/pages/quiz-session/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';

import { getQuizSocket } from '@/shared/utils/socket';
import QuizBackground from './ui/QuizBackground';
Expand All @@ -10,23 +9,24 @@ import QuizLoading from './ui/QuizLoading';
import { toastController } from '@/features/toast/model/toastController';

export default function QuizSession() {
const { pinCode } = useParams();
const socket = getQuizSocket();
const toast = toastController();
const [isLoading, setIsLoading] = useState(true);
const [isQuizEnd, setIsQuizEnd] = useState(false);
const [reactionStats, setReactionStats] = useState({
easy: 0,
hard: 0,
});
const [tick, setTick] = useState({ currentTime: 0, elapsedTime: 0, remainingTime: 0 });
const [quiz, setQuiz] = useState<QuizData>({
id: '',
content: '',
choices: [],
});

const totalReactions = reactionStats.easy + reactionStats.hard;
const easyPercentage = totalReactions ? (reactionStats.easy / totalReactions) * 100 : 50;
const handleTick = (response: any) => {
setTick(response);
};

const handleTimeEnd = () => {
setIsQuizEnd(true);
};

useEffect(() => {
const quizPromise = new Promise((resolve, reject) => {
Expand Down Expand Up @@ -62,24 +62,22 @@ export default function QuizSession() {
setIsLoading(false);
});

socket.on('timer end', () => {
setIsQuizEnd(true);
});
socket.on('timer tick', handleTick);
socket.on('time end', handleTimeEnd);

return () => {
socket.off('timer end', () => {});
socket.off('time end', handleTimeEnd);
socket.off('timer tick', handleTick);
};
}, []);

return (
<>
{isLoading ? (
<QuizLoading />
) : (
<div>
<QuizHeader />
<QuizBackground easyPercentage={easyPercentage} />
<QuizBox reactionStats={reactionStats} setReactionStats={setReactionStats} quiz={quiz} />
{isLoading && !isQuizEnd && <QuizLoading />}
{!isLoading && !isQuizEnd && (
<div className="relative w-full">
<QuizHeader tick={tick} />
<QuizBox quiz={quiz} tick={tick} />
</div>
)}
{isQuizEnd && <QuizEnd />}
Expand Down
50 changes: 34 additions & 16 deletions packages/client/src/pages/quiz-session/ui/QuizBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,46 @@ import { Dispatch, SetStateAction, useState, useRef, useEffect, useCallback } fr
import { getQuizSocket } from '@/shared/utils/socket';
import { getCookie } from '@/shared/utils/cookie';
import { useParams } from 'react-router-dom';
import AfterQuizSubmit from './AfterQuizSubmit';
import QuizBackground from './QuizBackground';
interface ReactionData {
easy: number;
hard: number;
}

export interface StatisticsData {
averageTime: number;
participantRate: number;
solveRate: number;
totalSubmit: number;
}

interface QuizBoxProps {
reactionStats: ReactionData;
setReactionStats: Dispatch<SetStateAction<ReactionData>>;
quiz: QuizData;
tick: { currentTime: number; elapsedTime: number; remainingTime: number };
}

export default function QuizBox({ reactionStats, setReactionStats, quiz }: QuizBoxProps) {
export default function QuizBox({ quiz, tick }: QuizBoxProps) {
const { pinCode } = useParams();
const [selectedAnswer, setSelectedAnswer] = useState<number[]>([]);
const [hasSubmitted, setHasSubmitted] = useState(false);
const [reactionStats, setReactionStats] = useState<ReactionData>({
easy: 0,
hard: 0,
});
const [participantStatistics, setParticipantStatistics] = useState<StatisticsData>({
averageTime: 0,
participantRate: 0,
solveRate: 0,
totalSubmit: 0,
});
const easyButtonRef = useRef<HTMLButtonElement>(null);
const hardButtonRef = useRef<HTMLButtonElement>(null);
const socket = getQuizSocket();
const [tick, setTick] = useState({ currentTime: 0, elapsedTime: 0, remainingTime: 0 });

const totalReactions = reactionStats.easy + reactionStats.hard;
const easyPercentage = totalReactions ? (reactionStats.easy / totalReactions) * 100 : 50;

const handleSelectAnswer = (idx: number) => {
setSelectedAnswer((prev) => {
if (prev.includes(idx)) {
Expand All @@ -38,7 +59,6 @@ export default function QuizBox({ reactionStats, setReactionStats, quiz }: QuizB
pinCode: pinCode,
submitTime: tick.elapsedTime,
});
console.log(selectedAnswer);
setHasSubmitted(true);
};

Expand All @@ -65,27 +85,23 @@ export default function QuizBox({ reactionStats, setReactionStats, quiz }: QuizB
setReactionStats(data);
}, []);

const handleParticipantStatistics = (response: StatisticsData) => {
setParticipantStatistics(response);
};

useEffect(() => {
socket.on('emoji', handleReactionUpdate);
socket.on('participant statistics', handleParticipantStatistics);

socket.on('timer tick', (response) => {
setTick(response);
});

socket.on('participant statistics', (response) => {
console.log('participant statistics', response);
});

socket.on('time end', (response) => {
console.log('time end', response);
});
return () => {
socket.off('emoji', handleReactionUpdate);
socket.off('participant statistics', handleParticipantStatistics);
};
}, []);

return (
<>
<QuizBackground easyPercentage={easyPercentage} />
<div className="relative z-10 p-6 max-w-4xl mx-auto mb-8">
<div className="bg-white/80 backdrop-blur-sm rounded-2xl shadow-lg p-6 mb-12">
<div className="flex items-center justify-between mb-6">
Expand Down Expand Up @@ -154,6 +170,8 @@ export default function QuizBox({ reactionStats, setReactionStats, quiz }: QuizB
</button>
</div>
</div>

{<AfterQuizSubmit {...participantStatistics} />}
</>
);
}
8 changes: 6 additions & 2 deletions packages/client/src/pages/quiz-session/ui/QuizHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { useEffect, useState } from 'react';

import { getQuizSocket } from '@/shared/utils/socket';

export default function QuizHeader() {
interface QuizHeaderProps {
tick: { currentTime: number; elapsedTime: number; remainingTime: number };
}

export default function QuizHeader({ tick }: QuizHeaderProps) {
const socket = getQuizSocket();
const [submitStatus, setSubmitStatus] = useState<{ count: number; total: number }>({
count: 0,
Expand All @@ -27,7 +31,7 @@ export default function QuizHeader() {
<div className="text-lg text-black-400 font-semibold">
{submitStatus.count} / {submitStatus.total}명 제출
</div>
<div className="text-bold-lg">남은 시간</div>
<div className="text-bold-lg">{tick.remainingTime}초 남음</div>
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/pages/quiz-session/ui/QuizLoading.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const QuizLoading = () => {
return (
<div className="min-h-screen w-full flex flex-col items-center justify-center bg-gradient-to-b from-slate-50 to-white">
<div className="h-[calc(100vh-60px)] w-full flex flex-col items-center justify-center bg-gradient-to-b from-slate-50 to-white">
<div className="relative p-12 rounded-3xl bg-white/30 backdrop-blur-lg shadow-[0_8px_30px_rgb(0,0,0,0.05)] border border-white/20">
<div className="relative flex flex-col items-center">
<div className="relative w-32 h-32">
Expand Down
15 changes: 15 additions & 0 deletions packages/client/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,21 @@ export default {
from: { transform: 'rotate(0deg)' },
to: { transform: 'rotate(360deg)' },
},
floatDown: {
'0%': {
transform: 'translateY(-100px)',
opacity: 0,
},
'100%': {
transform: 'translateY(0)',
opacity: 1,
},
},
swing: {
'0%': { transform: 'rotate(0deg) translateY(0)' },
'50%': { transform: 'rotate(30deg) translateY(-20px)' },
'100%': { transform: 'rotate(0deg) translateY(0)' },
},
},
},
},
Expand Down

0 comments on commit 72755f3

Please sign in to comment.