Skip to content

Commit

Permalink
[FE] - 마스터 그래프 페이지 버그 해결 (#150)
Browse files Browse the repository at this point in the history
* fix: favicon href url 변경

* fix: font 에러를 절대 경로로 수정하여 해결

* fix: 초기값을 빈 객체로 수정

* feat: 초를 분, 시간으로 변환하는 formatelapsedTime 유틸 함수 추가

* feat: 보이는 시간을 formatElapsedTime 유틸 함수로 사용하여 분, 시간을 보이도록 수정

* refactor: 이모지 그래프 숫자 소수점을 보이지 않도록 수정

* feat: AnswerChart에서 퀴즈에 알맞는 선지를 보이도록 수정

- tooltip, legend x축 값을 count에서 참여자 수로 변경

* style: 마스터 페이지 그래프 height 수정

* feat: tickcount를 약수에 맞게 설정 및 에러 수정

* fix: 띄어쓰기 삭제

* style: 그리드아이템 캐릭터 input 크기 수정

* fix: answer 번호 변수 추가
  • Loading branch information
dooohun authored Dec 1, 2024
1 parent 3678d82 commit 2276190
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 23 deletions.
2 changes: 1 addition & 1 deletion packages/client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/public/you-quiz.svg" />
<link rel="icon" type="image/svg+xml" href="/you-quiz.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>You-Quiz 실시간 퀴즈 플랫폼</title>
</head>
Expand Down
6 changes: 3 additions & 3 deletions packages/client/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@
font-family: "Pretendard";
font-weight: 400;
font-style: normal;
src: url("./assets/fonts/Pretendard-Regular.woff2") format("woff2");
src: url("/src/shared/assets/fonts/Pretendard-Regular.woff2") format("woff2");
}

@font-face {
font-family: "Pretendard";
font-weight: 500;
font-style: normal;
src: url("./assets/fonts/Pretendard-Medium.woff2") format("woff2");
src: url("/src/shared/assets/fonts/Pretendard-Medium.woff2") format("woff2");
}

@font-face {
font-family: "Pretendard";
font-weight: 700;
font-style: normal;
src: url("./assets/fonts/Pretendard-Bold.woff2") format("woff2");
src: url("/src/shared/assets/fonts/Pretendard-Bold.woff2") format("woff2");
}

body {
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/pages/quiz-list/ui/ClassItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export default function ClassItem({ index, quizList }: ClassItemProps) {
{quizList.quizzes.length === 0 && <span>퀴즈가 없습니다.</span>}
{quizList.quizzes.map((quizData, quizIndex) => (
<span key={`${quizData.content} ${quizIndex}`}>
<span className="text-md font-bold text-secondary">Q {quizIndex + 1} : </span>
<span className="text-md font-bold text-secondary">Q{quizIndex + 1}: </span>
<span className="text-md font-semibold text-gray-600">{quizData.content}</span>
</span>
))}
Expand Down
12 changes: 8 additions & 4 deletions packages/client/src/pages/quiz-master-session/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface HistoryItem {
user: string;
submitTime: number;
elapsedTime: number;
displayTime: string;
}

export default function QuizMasterSession() {
Expand Down Expand Up @@ -109,8 +110,7 @@ export default function QuizMasterSession() {
</p>
<div className="mb-2">
<button
className={`bg-blue-500 text-white px-4 py-2 rounded-md disabled:bg-blue-300 disabled:cursor-not-allowed disabled:opacity-50
`}
className={`bg-blue-500 text-white px-4 py-2 rounded-md disabled:bg-blue-300 disabled:cursor-not-allowed disabled:opacity-50`}
onClick={handleNextQuiz}
disabled={Math.floor(tick.remainingTime / 1000) !== 0}
>
Expand All @@ -121,8 +121,12 @@ export default function QuizMasterSession() {
</div>
</div>
<StatisticsGroup participantStatistics={masterStatistics} />
<div className="grid grid-cols-[3fr_1fr] gap-4 mx-5 h-[650px]">
<AnswerGraph answerStats={masterStatistics.choiceStatus} />
<div className="grid grid-cols-[3fr_1fr] gap-4 mx-5 h-[calc(100vh-300px)]">
<AnswerGraph
answerStats={masterStatistics.choiceStatus}
participantCount={masterStatistics.participantLength}
quizData={quizData}
/>
<div>
<RecentSubmittedAnswers
userSubmitHistory={masterStatistics.submitHistory}
Expand Down
58 changes: 48 additions & 10 deletions packages/client/src/pages/quiz-master-session/ui/AnswerChart.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { MasterStatisticsResponse } from '@youquiz/shared/interfaces/response';

import {
ResponsiveContainer,
BarChart,
Expand All @@ -10,25 +8,65 @@ import {
Bar,
Legend,
} from 'recharts';
import { useEffect, useState } from 'react';

import { MasterStatisticsResponse } from '@youquiz/shared/interfaces/response';
import { QuizData } from '@youquiz/shared/interfaces/utils/quizdata.interface';
import LoadingSpinner from '@/shared/assets/icons/loading-alt-loop.svg?react';

interface AnswerStatProps {
answerStats: MasterStatisticsResponse['choiceStatus'];
quizData: QuizData | null;
participantCount: number;
}

export default function AnswerGraph({ answerStats }: AnswerStatProps) {
const answerStatsArray = Object.entries(answerStats).map(([answer, count]) => ({
answer,
count,
}));
const calculateTickCount = (maxValue: number): number => {
const maxTicks = 5;

const divisors = Array.from({ length: maxValue }, (_, i) => i + 1).filter(
(num) => maxValue % num === 0,
);
return Math.max(divisors[Math.min(divisors.length - 1, maxTicks - 1)], 2);
};

export default function AnswerGraph({ answerStats, quizData, participantCount }: AnswerStatProps) {
const [answerStatsArray, setAnswerStatsArray] = useState<{ answer: string; count: number }[]>([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
if (quizData?.choices) {
const formattedData = Object.entries(answerStats).map(([key, count]) => ({
answer:
`${parseInt(key) + 1}번: ${quizData.choices[parseInt(key)].content}` || `답변 ${key}`,
count,
}));
setAnswerStatsArray(formattedData);
setLoading(false);
}
}, [quizData, answerStats]);

const tickCount = calculateTickCount(participantCount);

if (loading) {
return (
<div className="flex items-center justify-center h-full">
<LoadingSpinner width={50} height={50} />
</div>
);
}
return (
<ResponsiveContainer width="100%" height="100%">
<BarChart data={answerStatsArray} barSize={60}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="answer" axisLine={false} tickLine={false} />
<YAxis axisLine={false} tickLine={false} tickCount={6} />
<Tooltip />
<Legend />
<YAxis
axisLine={false}
tickLine={false}
tickCount={tickCount}
domain={[0, participantCount]}
/>
<Tooltip formatter={(value: number) => [`${value}명`, '참여자 수']} />
<Legend formatter={() => '참여자 수'} />
<Bar dataKey="count" fillOpacity={0.8} />
</BarChart>
</ResponsiveContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default function EmojiChart({ reactionStats }: EmojiChartProps) {
const calculatePercentage = (count: number) => {
if (totalVotes === 0) return 50;

return Number(((count / totalVotes) * 100).toFixed(1));
return Number(((count / totalVotes) * 100).toFixed(0));
};

const results = [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { formatElapsedTime } from '@/shared/utils/formatElapsedTime';
import { useEffect } from 'react';

interface HistoryItem {
user: string;
submitTime: number;
elapsedTime: number;
displayTime: string;
}

interface RecentSubmittedAnswersProps {
Expand All @@ -29,6 +31,7 @@ export default function RecentSubmittedAnswers({
user,
submitTime,
elapsedTime: existedHistory ? existedHistory.elapsedTime : 0,
displayTime: existedHistory ? existedHistory.displayTime : '',
};
});

Expand All @@ -49,6 +52,7 @@ export default function RecentSubmittedAnswers({
prev.map((item) => ({
...item,
elapsedTime: item.elapsedTime + 1,
displayTime: formatElapsedTime(item.elapsedTime + 1),
})),
);
}, 1000);
Expand Down Expand Up @@ -79,7 +83,7 @@ export default function RecentSubmittedAnswers({
</div>
<div>
<p className="font-medium">{item.user}</p>
<p className="text-sm text-gray-500">{item.elapsedTime}초 전 제출</p>
<p className="text-sm text-gray-500">{item.displayTime || '방금 전'}</p>
</div>
</div>
<div className="flex items-center space-x-4">
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/pages/quiz-wait/ui/UserGridItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export default function UserGridItem({ participant, isMine, otherMessage }: User
onChange={handleMessageChange}
onKeyDown={handleEnterKeyDown}
maxLength={MAX_MESSAGE_LENGTH}
className="absolute -top-7 rounded-md shadow-sm outline-none px-2 w-40 h-6 text-sm"
className="absolute -top-7 rounded-md shadow-sm outline-none px-2 w-32 h-6 text-sm"
/>
<div
className="absolute inset-0 -top-1 left-12 w-0 h-0
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/shared/constants/initialState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const INITIAL_TICK: TimerTickResponse = {

export const INITIAL_MASTER_STATISTICS: MasterStatisticsResponse = {
averageTime: 0,
choiceStatus: { 0: 0, 1: 0, 2: 0, 3: 0 },
choiceStatus: {},
participantLength: 0,
participantRate: 0,
solveRate: 0,
Expand Down
13 changes: 13 additions & 0 deletions packages/client/src/shared/utils/formatElapsedTime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export function formatElapsedTime(elapsedTime: number) {
const rtf = new Intl.RelativeTimeFormat('ko', { numeric: 'auto' });

if (elapsedTime >= 3600) {
const hours = Math.floor(elapsedTime / 3600);
return rtf.format(-hours, 'hour');
} else if (elapsedTime >= 60) {
const minutes = Math.floor(elapsedTime / 60);
return rtf.format(-minutes, 'minute');
} else {
return rtf.format(-elapsedTime, 'second');
}
}

0 comments on commit 2276190

Please sign in to comment.