Skip to content

Commit 79de5aa

Browse files
committed
feat: 퀴즈 결과 모달 추가 및 QuizStep 컴포넌트 개선
- QuizStep 컴포넌트에 퀴즈 결과를 보여주는 QuizResultModal을 추가하여 사용자 경험을 향상시킴 - 정답 여부에 따라 적절한 메시지를 표시하고, 다음 퀴즈로 넘어가는 기능을 구현함 - 관련 스타일 파일을 추가하여 모달의 디자인을 개선함
1 parent 719c9a8 commit 79de5aa

File tree

4 files changed

+152
-16
lines changed

4 files changed

+152
-16
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import styled from '@emotion/styled';
2+
3+
const Overlay = styled.div`
4+
position: fixed;
5+
top: 0;
6+
left: 0;
7+
right: 0;
8+
bottom: 0;
9+
background-color: rgba(0, 0, 0, 0.7);
10+
display: flex;
11+
justify-content: center;
12+
align-items: center;
13+
z-index: 1000;
14+
padding: 0 20px;
15+
`;
16+
17+
const ModalContainer = styled.div`
18+
width: calc(100% - 40px);
19+
max-width: calc(${({ theme }) => theme.breakpoints.mobile} - 40px);
20+
min-height: 280px;
21+
background: ${({ theme }) => theme.palette.common.white};
22+
border-radius: 14px;
23+
padding: 40px 24px;
24+
display: flex;
25+
flex-direction: column;
26+
align-items: center;
27+
`;
28+
29+
const IconWrapper = styled.div`
30+
margin-bottom: 16px;
31+
display: flex;
32+
justify-content: center;
33+
align-items: center;
34+
`;
35+
36+
const ResultText = styled.p`
37+
${({ theme }) => theme.typography.title.display4};
38+
color: ${({ theme }) => theme.palette.common.black};
39+
text-align: center;
40+
margin-bottom: 8px;
41+
`;
42+
43+
const SubText = styled.p`
44+
${({ theme }) => theme.typography.body.body1};
45+
color: ${({ theme }) => theme.palette.gray['gray-6']};
46+
text-align: center;
47+
margin-bottom: 24px;
48+
`;
49+
50+
const CorrectAnswerText = styled.p`
51+
${({ theme }) => theme.typography.title.subhead1};
52+
color: ${({ theme }) => theme.palette.main.pink[60]};
53+
text-align: center;
54+
margin-bottom: 24px;
55+
`;
56+
57+
const NextButton = styled.button`
58+
width: 100%;
59+
height: 52px;
60+
border: none;
61+
border-radius: 10px;
62+
background: linear-gradient(
63+
180deg,
64+
${({ theme }) => theme.palette.main.pink[50]},
65+
${({ theme }) => theme.palette.main.pink[80]}
66+
);
67+
${({ theme }) => theme.typography.title.subhead1};
68+
color: ${({ theme }) => theme.palette.common.white};
69+
cursor: pointer;
70+
71+
&:hover {
72+
opacity: 0.9;
73+
}
74+
`;
75+
76+
export {
77+
Overlay,
78+
ModalContainer,
79+
IconWrapper,
80+
ResultText,
81+
SubText,
82+
CorrectAnswerText,
83+
NextButton,
84+
};
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { QuizCorrectIcon, QuizWrongIcon } from '@/assets/icons';
2+
import {
3+
Overlay,
4+
ModalContainer,
5+
IconWrapper,
6+
ResultText,
7+
SubText,
8+
CorrectAnswerText,
9+
NextButton,
10+
} from './QuizResultModal.styles';
11+
12+
interface QuizResultModalProps {
13+
isCorrect: boolean;
14+
correctAnswer: string;
15+
onNext: () => void;
16+
}
17+
18+
const QuizResultModal = ({
19+
isCorrect,
20+
correctAnswer,
21+
onNext,
22+
}: QuizResultModalProps) => {
23+
return (
24+
<Overlay>
25+
<ModalContainer>
26+
<IconWrapper>
27+
{isCorrect ? <QuizCorrectIcon /> : <QuizWrongIcon />}
28+
</IconWrapper>
29+
<ResultText>{isCorrect ? '정답이에요!' : '아쉽네요!'}</ResultText>
30+
<SubText>
31+
{isCorrect ? '역시 밈잘알이시군요!' : '다음에는 꼭 맞춰보아요!'}
32+
</SubText>
33+
{!isCorrect && (
34+
<CorrectAnswerText>
35+
정답은 &quot;{correctAnswer}&quot; 입니다
36+
</CorrectAnswerText>
37+
)}
38+
<NextButton onClick={onNext}>다음 퀴즈 풀기</NextButton>
39+
</ModalContainer>
40+
</Overlay>
41+
);
42+
};
43+
44+
export default QuizResultModal;

apps/web/src/pages/MemeQuizPage/components/QuizStep/index.tsx

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useState } from 'react';
22
import { LinkCopiedIcon } from '@/assets/icons';
3+
import QuizResultModal from './QuizResultModal';
34
import {
45
Container,
56
Content,
@@ -27,30 +28,36 @@ interface QuizStepProps {
2728
}[];
2829
};
2930
currentStep: string;
30-
isFirstQuiz: boolean;
31-
onBefore: () => void;
3231
onAnswer: (currentStep: string, isRight: boolean) => void;
3332
currentAnswer?: boolean;
3433
}
3534

36-
const QuizStep = ({
37-
quiz,
38-
currentStep,
39-
40-
onAnswer,
41-
}: QuizStepProps) => {
35+
const QuizStep = ({ quiz, currentStep, onAnswer }: QuizStepProps) => {
4236
const [selectedAnswer, setSelectedAnswer] = useState<number | null>(null);
37+
const [showResultModal, setShowResultModal] = useState(false);
4338

4439
const handleAnswerSelect = (index: number) => {
4540
setSelectedAnswer(index);
4641
};
4742

4843
const handleNext = () => {
44+
if (selectedAnswer !== null) {
45+
setShowResultModal(true);
46+
}
47+
};
48+
49+
const handleNextQuiz = () => {
4950
if (selectedAnswer !== null) {
5051
onAnswer(currentStep, quiz.questions[selectedAnswer].isRight);
52+
setShowResultModal(false);
53+
setSelectedAnswer(null);
5154
}
5255
};
5356

57+
const getCorrectAnswer = () => {
58+
return quiz.questions.find((q) => q.isRight)?.message || '';
59+
};
60+
5461
const stepNumber = currentStep.replace('quiz', '');
5562

5663
return (
@@ -93,6 +100,14 @@ const QuizStep = ({
93100
다음
94101
</BottomButton>
95102
</BottomContainer>
103+
104+
{showResultModal && selectedAnswer !== null && (
105+
<QuizResultModal
106+
isCorrect={quiz.questions[selectedAnswer].isRight}
107+
correctAnswer={getCorrectAnswer()}
108+
onNext={handleNextQuiz}
109+
/>
110+
)}
96111
</Container>
97112
);
98113
};

apps/web/src/pages/MemeQuizPage/index.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ const MemeQuizPage = () => {
6666
};
6767
}, [quizData]);
6868

69-
const { Funnel, step, setStep } = useFunnel<keyof typeof quizSteps>(
69+
const { Funnel, setStep } = useFunnel<keyof typeof quizSteps>(
7070
quizSteps[stepsArray[0]],
7171
);
7272

@@ -93,14 +93,7 @@ const MemeQuizPage = () => {
9393
<QuizStep
9494
quiz={quiz}
9595
currentStep={`quiz${index + 1}`}
96-
isFirstQuiz={stepsArray.indexOf(step) === 0}
9796
currentAnswer={stepAnswers[`quiz${index + 1}`]}
98-
onBefore={() => {
99-
const currentStepIndex = stepsArray.indexOf(step);
100-
if (currentStepIndex <= 0) return;
101-
102-
onNext(stepsArray[currentStepIndex - 1]);
103-
}}
10497
onAnswer={(currentStep, isRight) => {
10598
setStepAnswers((prev) => ({
10699
...prev,

0 commit comments

Comments
 (0)