Skip to content

Commit a050181

Browse files
committed
feat: 밈 퀴즈 화면 개발
- 더미 데이터를 이용하여 밈퀴즈 로직을 개발
1 parent 3907123 commit a050181

File tree

7 files changed

+522
-1
lines changed

7 files changed

+522
-1
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import styled from '@emotion/styled';
2+
3+
export const Container = styled.div`
4+
display: flex;
5+
flex-direction: column;
6+
align-items: center;
7+
padding: 20px;
8+
gap: 20px;
9+
width: 100%;
10+
position: relative;
11+
`;
12+
13+
export const NavigationContainer = styled.div`
14+
position: absolute;
15+
top: 20px;
16+
left: 20px;
17+
`;
18+
19+
export const BackButton = styled.button`
20+
padding: 8px 16px;
21+
border-radius: 8px;
22+
border: 1px solid ${({ theme }) => theme.palette.gray[300]};
23+
background-color: ${({ theme }) => theme.palette.white};
24+
color: ${({ theme }) => theme.palette.gray[900]};
25+
cursor: pointer;
26+
transition: all 0.2s ease-in-out;
27+
display: flex;
28+
align-items: center;
29+
gap: 4px;
30+
31+
&:hover {
32+
background-color: ${({ theme }) => theme.palette.gray[100]};
33+
}
34+
35+
&:disabled {
36+
opacity: 0.5;
37+
cursor: not-allowed;
38+
}
39+
`;
40+
41+
export const QuizImage = styled.img`
42+
width: 100%;
43+
max-width: 500px;
44+
height: auto;
45+
border-radius: 8px;
46+
`;
47+
48+
export const Title = styled.h1`
49+
${({ theme }) => theme.typography.heading.h3};
50+
color: ${({ theme }) => theme.palette.gray[900]};
51+
text-align: center;
52+
`;
53+
54+
export const Summary = styled.p`
55+
${({ theme }) => theme.typography.body.medium};
56+
color: ${({ theme }) => theme.palette.gray[700]};
57+
text-align: center;
58+
`;
59+
60+
export const QuestionContainer = styled.div`
61+
display: flex;
62+
flex-direction: column;
63+
gap: 10px;
64+
width: 100%;
65+
max-width: 500px;
66+
`;
67+
68+
export const Button = styled.button<{ isSelected: boolean }>`
69+
width: 100%;
70+
padding: 12px;
71+
border-radius: 8px;
72+
border: 1px solid ${({ theme }) => theme.palette.gray[300]};
73+
background-color: ${({ theme, isSelected }) =>
74+
isSelected ? theme.palette.primary : theme.palette.white};
75+
color: ${({ theme, isSelected }) =>
76+
isSelected ? theme.palette.white : theme.palette.gray[900]};
77+
cursor: pointer;
78+
transition: all 0.2s ease-in-out;
79+
80+
&:hover {
81+
background-color: ${({ theme, isSelected }) =>
82+
isSelected ? theme.palette.primaryDark : theme.palette.gray[100]};
83+
}
84+
85+
&:active {
86+
background-color: ${({ theme }) => theme.palette.primary};
87+
color: ${({ theme }) => theme.palette.white};
88+
transform: scale(0.98);
89+
}
90+
`;
91+
92+
export const ResultContainer = styled.div`
93+
display: flex;
94+
flex-direction: column;
95+
align-items: center;
96+
gap: 20px;
97+
text-align: center;
98+
`;
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import styled from '@emotion/styled';
2+
3+
export const Container = styled.div`
4+
display: flex;
5+
flex-direction: column;
6+
align-items: center;
7+
padding: 20px;
8+
gap: 20px;
9+
width: 100%;
10+
position: relative;
11+
`;
12+
13+
export const NavigationContainer = styled.div`
14+
position: absolute;
15+
top: 20px;
16+
left: 20px;
17+
`;
18+
19+
export const BackButton = styled.button`
20+
padding: 8px 16px;
21+
border-radius: 8px;
22+
border: 1px solid ${({ theme }) => theme.palette.gray[300]};
23+
background-color: ${({ theme }) => theme.palette.white};
24+
color: ${({ theme }) => theme.palette.gray[900]};
25+
cursor: pointer;
26+
transition: all 0.2s ease-in-out;
27+
display: flex;
28+
align-items: center;
29+
gap: 4px;
30+
31+
&:hover {
32+
background-color: ${({ theme }) => theme.palette.gray[100]};
33+
}
34+
35+
&:disabled {
36+
opacity: 0.5;
37+
cursor: not-allowed;
38+
}
39+
`;
40+
41+
export const QuizImage = styled.img`
42+
width: 100%;
43+
max-width: 500px;
44+
height: auto;
45+
border-radius: 8px;
46+
`;
47+
48+
export const Title = styled.h1`
49+
${({ theme }) => theme.typography.heading.h3};
50+
color: ${({ theme }) => theme.palette.gray[900]};
51+
text-align: center;
52+
`;
53+
54+
export const Summary = styled.p`
55+
${({ theme }) => theme.typography.body.medium};
56+
color: ${({ theme }) => theme.palette.gray[700]};
57+
text-align: center;
58+
`;
59+
60+
export const QuestionContainer = styled.div`
61+
display: flex;
62+
flex-direction: column;
63+
gap: 10px;
64+
width: 100%;
65+
max-width: 500px;
66+
`;
67+
68+
export const Button = styled.button<{ isSelected?: boolean }>`
69+
width: 100%;
70+
padding: 12px;
71+
border-radius: 8px;
72+
border: 1px solid ${({ theme }) => theme.palette.gray[300]};
73+
background-color: ${({ theme, isSelected }) =>
74+
isSelected ? theme.palette.primary : theme.palette.white};
75+
color: ${({ theme, isSelected }) =>
76+
isSelected ? theme.palette.white : theme.palette.gray[900]};
77+
cursor: pointer;
78+
transition: all 0.2s ease-in-out;
79+
80+
&:hover {
81+
background-color: ${({ theme, isSelected }) =>
82+
isSelected ? theme.palette.primaryDark : theme.palette.gray[100]};
83+
}
84+
`;
85+
86+
export const ResultContainer = styled.div`
87+
display: flex;
88+
flex-direction: column;
89+
align-items: center;
90+
gap: 20px;
91+
text-align: center;
92+
`;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as S from './MemeQuizResult.styles';
2+
3+
interface MemeQuizResultPageProps {
4+
rightCount: number;
5+
onReset: () => void;
6+
}
7+
8+
const MemeQuizResult = ({ rightCount, onReset }: MemeQuizResultPageProps) => {
9+
return (
10+
<S.Container>
11+
<S.NavigationContainer>
12+
<S.BackButton onClick={onReset}>← 다시 풀기</S.BackButton>
13+
</S.NavigationContainer>
14+
<S.ResultContainer>
15+
<S.Title>퀴즈 결과</S.Title>
16+
<S.Summary>{rightCount}개 맞추셨습니다!</S.Summary>
17+
</S.ResultContainer>
18+
</S.Container>
19+
);
20+
};
21+
22+
export default MemeQuizResult;
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import styled from '@emotion/styled';
2+
3+
export const Container = styled.div`
4+
display: flex;
5+
flex-direction: column;
6+
align-items: center;
7+
padding: 20px;
8+
gap: 20px;
9+
width: 100%;
10+
position: relative;
11+
`;
12+
13+
export const NavigationContainer = styled.div`
14+
position: absolute;
15+
top: 20px;
16+
left: 20px;
17+
`;
18+
19+
export const BackButton = styled.button`
20+
padding: 8px 16px;
21+
border-radius: 8px;
22+
border: 1px solid ${({ theme }) => theme.palette.gray[300]};
23+
background-color: ${({ theme }) => theme.palette.white};
24+
color: ${({ theme }) => theme.palette.gray[900]};
25+
cursor: pointer;
26+
transition: all 0.2s ease-in-out;
27+
display: flex;
28+
align-items: center;
29+
gap: 4px;
30+
31+
&:hover {
32+
background-color: ${({ theme }) => theme.palette.gray[100]};
33+
}
34+
35+
&:disabled {
36+
opacity: 0.5;
37+
cursor: not-allowed;
38+
}
39+
`;
40+
41+
export const QuizImage = styled.img`
42+
width: 100%;
43+
max-width: 500px;
44+
height: auto;
45+
border-radius: 8px;
46+
`;
47+
48+
export const Title = styled.h1`
49+
${({ theme }) => theme.typography.heading.h3};
50+
color: ${({ theme }) => theme.palette.gray[900]};
51+
text-align: center;
52+
`;
53+
54+
export const Summary = styled.p`
55+
${({ theme }) => theme.typography.body.medium};
56+
color: ${({ theme }) => theme.palette.gray[700]};
57+
text-align: center;
58+
`;
59+
60+
export const QuestionContainer = styled.div`
61+
display: flex;
62+
flex-direction: column;
63+
gap: 10px;
64+
width: 100%;
65+
max-width: 500px;
66+
`;
67+
68+
export const Button = styled.button<{ isSelected: boolean }>`
69+
width: 100%;
70+
padding: 12px;
71+
border-radius: 8px;
72+
border: 1px solid ${({ theme }) => theme.palette.gray[300]};
73+
background-color: ${({ theme, isSelected }) =>
74+
isSelected ? theme.palette.primary : theme.palette.white};
75+
color: ${({ theme, isSelected }) =>
76+
isSelected ? theme.palette.white : theme.palette.gray[900]};
77+
cursor: pointer;
78+
transition: all 0.2s ease-in-out;
79+
80+
&:hover {
81+
background-color: ${({ theme, isSelected }) =>
82+
isSelected ? theme.palette.primaryDark : theme.palette.gray[100]};
83+
}
84+
85+
&:active {
86+
background-color: ${({ theme }) => theme.palette.primary};
87+
color: ${({ theme }) => theme.palette.white};
88+
transform: scale(0.98);
89+
}
90+
`;
91+
92+
export const ResultContainer = styled.div`
93+
display: flex;
94+
flex-direction: column;
95+
align-items: center;
96+
gap: 20px;
97+
text-align: center;
98+
`;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import * as S from './QuizStep.styles';
2+
3+
interface Question {
4+
message: string;
5+
isRight: boolean;
6+
}
7+
8+
interface QuizItem {
9+
title: string;
10+
summary: string;
11+
image: string;
12+
questions: Question[];
13+
}
14+
15+
interface QuizStepProps {
16+
quiz: QuizItem;
17+
currentStep: string;
18+
isFirstQuiz: boolean;
19+
onBefore: () => void;
20+
onAnswer: (currentStep: string, isRight: boolean) => void;
21+
currentAnswer: boolean | undefined;
22+
}
23+
24+
const QuizStep = ({
25+
quiz,
26+
currentStep,
27+
isFirstQuiz,
28+
onBefore,
29+
onAnswer,
30+
currentAnswer,
31+
}: QuizStepProps) => {
32+
return (
33+
<S.Container>
34+
{!isFirstQuiz && (
35+
<S.NavigationContainer>
36+
<S.BackButton onClick={onBefore}>← 이전</S.BackButton>
37+
</S.NavigationContainer>
38+
)}
39+
<S.Title>{quiz.title}</S.Title>
40+
<S.Summary>{quiz.summary}</S.Summary>
41+
<S.QuizImage src={quiz.image} alt={quiz.title} />
42+
<S.QuestionContainer>
43+
{quiz.questions.map((question, index) => {
44+
return (
45+
<S.Button
46+
key={index}
47+
onClick={() => onAnswer(currentStep, question.isRight)}
48+
isSelected={currentAnswer === question.isRight}
49+
>
50+
{question.message}
51+
</S.Button>
52+
);
53+
})}
54+
</S.QuestionContainer>
55+
</S.Container>
56+
);
57+
};
58+
59+
export default QuizStep;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import MemeQuizResultPage from './MemeQuizResult';
2+
import QuizStep from './QuizStep';
3+
4+
export { MemeQuizResultPage, QuizStep };

0 commit comments

Comments
 (0)