Skip to content

Commit

Permalink
feat: document detail - quiz
Browse files Browse the repository at this point in the history
+ fix: quiz card
  • Loading branch information
rabyeoljji committed Nov 26, 2024
1 parent cd777d4 commit a782e48
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 38 deletions.
4 changes: 2 additions & 2 deletions src/features/document/config/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ export const addDocumentButtons = [

export const quizTypeFilters = [
{ key: 'ALL', label: '전체' },
{ key: 'MULTIPLE', label: '객관식' },
{ key: 'OX', label: 'O/X' },
{ key: 'MULTIPLE_CHOICE', label: '객관식' },
{ key: 'MIX_UP', label: 'O/X' },
] as const
27 changes: 20 additions & 7 deletions src/features/document/screens/quiz.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
'use client'

import { Button } from '@/shared/components/ui/button'
import { useState } from 'react'
import { useEffect, useState } from 'react'
import { Switch } from '@/shared/components/ui/switch'
import Text from '@/shared/components/ui/text'
import { useQuizListContext } from '../contexts/quiz-list-context'
import QuizList from '@/features/quiz/components/quiz-list'
import QuizCard from '@/features/quiz/components/quiz-card'
import { quizzes } from '@/features/quiz/config'
import { quizTypeFilters } from '../config'
import QuizCardMenu from '@/features/quiz/components/quiz-card-menu'
import { useQuery } from '@tanstack/react-query'
import { queries } from '@/shared/lib/tanstack-query/query-keys'
import { useParams } from 'next/navigation'
import Loading from '@/shared/components/custom/loading'

const Quiz = () => {
const [quizType, setQuizType] = useState('ALL')
const { showAnswer, setShowAnswer } = useQuizListContext()
const { id } = useParams()
const [quizType, setQuizType] = useState<Quiz.Type | 'ALL'>('ALL')
const [answerMode, setAnswerMode] = useState(false)

const params =
quizType === 'ALL' ? { documentId: Number(id) } : { documentId: Number(id), quizType }

const { data, isPending } = useQuery(queries.quiz.listByDocument(params))

if (isPending) {
return <Loading center />
}

return (
<div className="flex flex-col items-center p-[20px] pb-[132px]">
Expand All @@ -35,13 +48,13 @@ const Quiz = () => {
<Text typography="text2-medium" className="mr-[8px] text-text-sub">
정답 표시
</Text>
<Switch onClick={() => setShowAnswer(!showAnswer)} />
<Switch checked={answerMode} onClick={() => setAnswerMode(!answerMode)} />
</div>
</div>

{/* 퀴즈 카드 */}
<QuizList>
{quizzes.map((quiz) => (
{data?.quizzes.map((quiz) => (
<QuizCard
header={
<div className="flex items-center justify-between text-icon-tertiary">
Expand All @@ -53,7 +66,7 @@ const Quiz = () => {
}
key={quiz.id}
quiz={quiz}
showExplanation={showAnswer}
answerMode={answerMode}
/>
))}
</QuizList>
Expand Down
2 changes: 1 addition & 1 deletion src/features/quiz/components/pick-drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const PickDrawer = () => {
{quizzes.map((quiz) => (
<QuizCard
key={quiz.id}
showAnswer
answerMode
header={
<div className="flex items-center justify-between text-icon-tertiary">
{/* 태그에는 pick 사유가 들어갈 예정 (오답 / 20초 이상 소요) */}
Expand Down
12 changes: 6 additions & 6 deletions src/features/quiz/components/quiz-card/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,22 +94,22 @@ export const WithBreadcrumb: Story = {
export const MultipleShowAnswer: Story = {
args: {
...Template.args,
showAnswer: true,
answerMode: true,
},
}

export const MultipleCorrectUserAnswer: Story = {
args: {
...Template.args,
showAnswer: true,
answerMode: true,
userAnswer: '기존의 배양육이 기존방식에서 생산되는 육류보다 토양이 비축된다',
},
}

export const MultipleWrongUserAnswer: Story = {
args: {
...Template.args,
showAnswer: true,
answerMode: true,
userAnswer: '배양육이 기존방식에서 생산되는 육류보다 토양이 비축된다',
},
}
Expand All @@ -118,7 +118,7 @@ export const OXCorrectUserAnswer: Story = {
args: {
...Template.args,
quiz: oxQuiz,
showAnswer: true,
answerMode: true,
userAnswer: 'correct',
},
}
Expand All @@ -127,8 +127,8 @@ export const OXWrongUserAnswer: Story = {
args: {
...Template.args,
quiz: oxQuiz,
showAnswer: true,
userAnswer: 'wrong',
answerMode: true,
userAnswer: 'incorrect',
},
}

Expand Down
47 changes: 26 additions & 21 deletions src/features/quiz/components/quiz-card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,36 @@
import Icon from '@/shared/components/custom/icon'
import Text from '@/shared/components/ui/text'
import { cn } from '@/shared/lib/utils'
import React, { useState } from 'react'
import React, { useEffect, useState } from 'react'

interface Props {
quiz: Quiz.Item
header: React.ReactNode
showAnswer?: boolean
answerMode?: boolean
showExplanation?: boolean
// userAnswer를 받으면 정답과 오답을 표시함
userAnswer?: string
}

const QuizCard = ({
quiz,
header,
showAnswer = false,
showExplanation = false,
userAnswer,
}: Props) => {
const QuizCard = ({ quiz, header, answerMode, showExplanation = false, userAnswer }: Props) => {
const [showAnswer, setShowAnswer] = useState(answerMode ?? false)
const [openExplanation, setOpenExplanation] = useState(showExplanation)

const shouldShowAnswer = showAnswer ?? openExplanation
useEffect(() => {
if (answerMode) {
setShowAnswer(true)
}

if (openExplanation) {
setShowAnswer(true)
} else {
!answerMode && setShowAnswer(false)
}
}, [answerMode, openExplanation])

const renderOptions = () => {
if (quiz.quizType === 'MULTIPLE_CHOICE' && quiz.options) {
const chosenAlphabet = userAnswer
const chosenOption = userAnswer
? String.fromCharCode(65 + quiz.options.findIndex((option) => option === userAnswer))
: undefined

Expand All @@ -38,9 +43,9 @@ const QuizCard = ({
key={option}
option={option}
// chosenAlphabet을 넘기면 정답과 오답을 표시함
chosenAlphabet={chosenAlphabet}
chosenOption={chosenOption}
optionAlphabet={String.fromCharCode(65 + index)}
showAnswer={shouldShowAnswer}
showAnswer={showAnswer}
isAnswer={quiz.answer === option}
/>
))}
Expand All @@ -50,14 +55,14 @@ const QuizCard = ({

return (
<div className="flex-center mt-[16px] gap-[6px]">
{(['correct', 'wrong'] as const).map((value) => (
{(['correct', 'incorrect'] as const).map((value) => (
<OXChoice
key={value}
value={value}
// chosenAnswer을 넘기면 정답과 오답을 표시함
chosenAnswer={userAnswer}
isAnswer={quiz.answer === value}
showAnswer={shouldShowAnswer}
showAnswer={showAnswer}
/>
))}
</div>
Expand Down Expand Up @@ -103,15 +108,15 @@ interface MultipleChoiceOptionProps {
optionAlphabet: string
showAnswer: boolean
isAnswer: boolean
chosenAlphabet?: string
chosenOption?: string
}

const MultipleChoiceOption = ({
option,
showAnswer,
optionAlphabet,
isAnswer,
chosenAlphabet,
chosenOption,
}: MultipleChoiceOptionProps) => {
return (
<Text
Expand All @@ -120,8 +125,8 @@ const MultipleChoiceOption = ({
'flex text-text-secondary',
showAnswer && isAnswer && 'text-text-accent',
showAnswer && !isAnswer && 'text-text-caption',
chosenAlphabet && isAnswer && 'text-text-success',
chosenAlphabet === optionAlphabet && !isAnswer && 'text-text-wrong'
chosenOption && isAnswer && 'text-text-success',
chosenOption === optionAlphabet && !isAnswer && 'text-text-wrong'
)}
>
<span className="mr-[2px]">{optionAlphabet}.</span>
Expand All @@ -136,7 +141,7 @@ const OXChoice = ({
showAnswer,
chosenAnswer,
}: {
value: 'correct' | 'wrong'
value: 'correct' | 'incorrect'
isAnswer: boolean
showAnswer: boolean
chosenAnswer?: string
Expand All @@ -153,7 +158,7 @@ const OXChoice = ({
)}
>
{value === 'correct' && 'O'}
{value === 'wrong' && 'X'}
{value === 'incorrect' && 'X'}
</Text>
)
}
27 changes: 27 additions & 0 deletions src/requests/quiz/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,30 @@ export const fetchDirectoryQuizzes = async ({ directoryId }: { directoryId: numb
throw error
}
}

export const fetchDocumentQuizzes = async ({
documentId,
quizType,
}: {
documentId: number
quizType?: Quiz.Type
}) => {
const session = await auth()

const params = quizType ? { 'quiz-type': quizType } : null

try {
const { data } = await http.get<Quiz.Response.GetDirectoryQuizzes>(
API_ENDPOINTS.QUIZ.GET.BY_DOCUMENT(documentId),
{
params,
headers: {
Authorization: `Bearer ${session?.user.accessToken}`,
},
}
)
return data
} catch (error: unknown) {
throw error
}
}
8 changes: 8 additions & 0 deletions src/shared/lib/tanstack-query/query-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,12 @@ export const queries = createQueryKeyStore({
queryFn: () => REQUEST.document.fetchDocumentDetail(documentId),
}),
},

quiz: {
listByDocument: (params: { documentId: number; quizType?: Quiz.Type }) => ({
queryKey: [params],
queryFn: () => REQUEST.quiz.fetchDocumentQuizzes(params),
enabled: !!params.documentId,
}),
},
})
2 changes: 1 addition & 1 deletion src/types/quiz.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type MultipleChoiceQuiz = {

type OXQuiz = {
quizType: 'MIX_UP'
answer: 'correct' | 'wrong'
answer: 'correct' | 'incorrect'
} & BaseQuiz

type CombineQuiz = MultipleChoiceQuiz | OXQuiz
Expand Down

0 comments on commit a782e48

Please sign in to comment.