-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: calendar * feat: quiz record * fix: name * feat: record detail 1 * refactor: 폴더 이동 * refactor: 폴더 구조 * fix: 주석 * fix: format error * fix: cspell * fix: build error * fix: build error * fix: format
- Loading branch information
1 parent
2c395d2
commit dd3b455
Showing
36 changed files
with
888 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ | |
"svgs", | ||
"swipeable", | ||
"taglib", | ||
"taglibs", | ||
"Tanstack", | ||
"Uncapitalize", | ||
"vaul", | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { FunctionComponent, PropsWithChildren } from 'react' | ||
import type { Metadata } from 'next' | ||
|
||
export const metadata: Metadata = {} | ||
|
||
interface InnerLayoutProps extends PropsWithChildren {} | ||
|
||
const Layout: FunctionComponent<InnerLayoutProps> = ({ children }) => { | ||
return <main>{children}</main> | ||
} | ||
|
||
export default Layout |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import QuizCard from '@/features/quiz/components/quiz-card' | ||
import { getQuizDetailRecord } from '@/requests/quiz/server' | ||
import Icon from '@/shared/components/custom/icon' | ||
import Text from '@/shared/components/ui/text' | ||
import { msToElapsedTimeKorean } from '@/shared/utils/time' | ||
|
||
interface Props { | ||
params: { | ||
id: string | ||
} | ||
searchParams: { | ||
type: Quiz.Set.Type | ||
name: string | ||
quizCount: number | ||
score: number | ||
} | ||
} | ||
|
||
const RecordDetailPage = async ({ params, searchParams }: Props) => { | ||
const date = params.id.split('_')[0] | ||
const quizSetId = params.id | ||
.split('_') | ||
.filter((value) => value !== date) | ||
.join('_') | ||
const quizSetType = searchParams.type | ||
const quizSetName = searchParams.name | ||
const quizCount = searchParams.quizCount | ||
const correctRate = Math.round((searchParams.score / searchParams.quizCount) * 100) | ||
|
||
const { totalElapsedTimeMs, quizzes } = await getQuizDetailRecord({ quizSetId, quizSetType }) | ||
|
||
return ( | ||
<main className="flex h-[calc(100dvh-54px)] flex-col overflow-y-auto"> | ||
<div className="flex-center flex-col gap-[40px] px-[16px] pb-[33px] pt-[20px]"> | ||
<div className="flex-center flex-col gap-[7px]"> | ||
<Text typography="title2">{quizSetName}</Text> | ||
<Text typography="text2-medium" color="secondary"> | ||
{date} | ||
</Text> | ||
</div> | ||
|
||
<div className="flex"> | ||
<div className="flex-center flex-col px-[30px]"> | ||
<div className="flex-center mb-[6px] size-[40px]"> | ||
<Icon name="speech-bubble-color" className="w-[36px]" /> | ||
</div> | ||
<Text typography="text2-medium" color="sub" className="mb-[2px]"> | ||
문제 수 | ||
</Text> | ||
<Text typography="subtitle2-bold">{quizCount}문제</Text> | ||
</div> | ||
<div className="flex-center flex-col border-x border-border-divider px-[30px]"> | ||
<div className="flex-center mb-[6px] size-[40px]"> | ||
<Icon name="timer-color" className="w-[30px]" /> | ||
</div> | ||
<Text typography="text2-medium" color="sub" className="mb-[2px]"> | ||
소요시간 | ||
</Text> | ||
<Text typography="subtitle2-bold">{msToElapsedTimeKorean(totalElapsedTimeMs)}</Text> | ||
</div> | ||
<div className="flex-center flex-col px-[30px]"> | ||
<div className="flex-center mb-[6px] size-[40px]"> | ||
<Icon name="correct-check-round" className="size-[34px]" /> | ||
</div> | ||
<Text typography="text2-medium" color="sub" className="mb-[2px]"> | ||
정답률 | ||
</Text> | ||
<Text typography="subtitle2-bold">{correctRate}%</Text> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div className="flex-center h-fit flex-col gap-[12px] bg-[var(--color-gray-50)] px-[16px] py-[20px]"> | ||
{quizzes.map((quiz, index) => ( | ||
<QuizCard | ||
key={quiz.id + '-idx:' + index} | ||
answerMode | ||
userAnswer={quiz.choseAnswer} | ||
header={ | ||
<div className="flex items-center justify-between pr-[6px] text-icon-tertiary"> | ||
{quiz.answer === quiz.choseAnswer ? ( | ||
<Text typography="text1-bold" color="right"> | ||
정답 | ||
</Text> | ||
) : ( | ||
<Text typography="text1-bold" color="critical"> | ||
오답 | ||
</Text> | ||
)} | ||
|
||
{quiz.quizSetType === 'COLLECTION_QUIZ_SET' ? ( | ||
<Text typography="text2-medium" color="caption"> | ||
{quiz.collectionName} | ||
</Text> | ||
) : ( | ||
<Text typography="text2-medium" color="caption"> | ||
{quiz.directoryName} | ||
{'>'} | ||
{quiz.documentName} | ||
</Text> | ||
)} | ||
</div> | ||
} | ||
quiz={quiz} | ||
/> | ||
))} | ||
</div> | ||
</main> | ||
) | ||
} | ||
|
||
export default RecordDetailPage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { FunctionComponent, PropsWithChildren } from 'react' | ||
import type { Metadata } from 'next' | ||
|
||
export const metadata: Metadata = {} | ||
|
||
interface InnerLayoutProps extends PropsWithChildren {} | ||
|
||
const Layout: FunctionComponent<InnerLayoutProps> = ({ children }) => { | ||
return <main>{children}</main> | ||
} | ||
|
||
export default Layout |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import AllRecordDetail from '@/features/record/screen/all-record-detail' | ||
|
||
const AllRecordPage = () => { | ||
return ( | ||
<main className="flex h-[calc(100dvh-54px)] flex-col gap-[32px] overflow-y-auto px-[16px] py-[24px]"> | ||
<AllRecordDetail /> | ||
</main> | ||
) | ||
} | ||
|
||
export default AllRecordPage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
'use client' | ||
|
||
import GoBackButton from '@/shared/components/custom/go-back-button' | ||
import Text from '@/shared/components/ui/text' | ||
import { useParams, usePathname } from 'next/navigation' | ||
|
||
const Header = () => { | ||
const pathname = usePathname() | ||
const params = useParams() | ||
|
||
const isDetailPage = params.id ? true : false | ||
const isAllPage = pathname === '/record/all' | ||
|
||
const headerText = isDetailPage ? '퀴즈 상세' : isAllPage ? '퀴즈 기록 전체' : '퀴즈 기록' | ||
|
||
return ( | ||
<header className="relative flex h-[54px] w-full items-center bg-background-base-01 px-[16px]"> | ||
<GoBackButton /> | ||
<Text typography="subtitle2-medium" className="center"> | ||
{headerText} | ||
</Text> | ||
</header> | ||
) | ||
} | ||
|
||
export default Header |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { FunctionComponent, PropsWithChildren } from 'react' | ||
import type { Metadata } from 'next' | ||
|
||
export const metadata: Metadata = {} | ||
|
||
interface LayoutProps extends PropsWithChildren { | ||
header: React.ReactNode | ||
} | ||
|
||
const Layout: FunctionComponent<LayoutProps> = ({ children, header }) => { | ||
return ( | ||
<> | ||
{header} | ||
{children} | ||
</> | ||
) | ||
} | ||
|
||
export default Layout |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import CustomCalendar from '@/features/record/calendar' | ||
import RecordItem from '@/features/record/components/record-item' | ||
import { getQuizRecords } from '@/requests/quiz/server' | ||
import Icon from '@/shared/components/custom/icon' | ||
import { Button } from '@/shared/components/ui/button' | ||
import Text from '@/shared/components/ui/text' | ||
import { formatDateKorean, getFormattedDate } from '@/shared/utils/date' | ||
import Link from 'next/link' | ||
|
||
interface Props { | ||
searchParams: { | ||
selectedDate: string | ||
} | ||
} | ||
|
||
const RecordPage = async ({ searchParams }: Props) => { | ||
const today = new Date() | ||
const selectedDate = searchParams.selectedDate ?? getFormattedDate(today) | ||
const { currentConsecutiveDays, maxConsecutiveDays, quizRecords } = await getQuizRecords() | ||
|
||
// 데이터가 많아지면 다른 방법으로 처리해보는 것을 고민 | ||
// 백엔드 측에 특정 solvedDate를 api 요청 시 보내면 일치하는 데이터를 보내주는 방법 제안해봐도 좋을 듯 | ||
const dateRecord = quizRecords.find((quizInfo) => quizInfo.solvedDate === selectedDate) | ||
|
||
return ( | ||
<main className="h-[calc(100dvh-54px)] overflow-y-auto px-[16px]"> | ||
<div className="flex-center flex-col gap-[8px] border-b border-border-divider pb-[20px] pt-[10px]"> | ||
<Text typography="title3"> | ||
<Text as={'span'} color="accent"> | ||
{currentConsecutiveDays} | ||
</Text> | ||
일 연속으로 푸는 중 | ||
</Text> | ||
|
||
<Text typography="text1-medium" color="caption"> | ||
최장 연속일: {maxConsecutiveDays}일 | ||
</Text> | ||
</div> | ||
|
||
<CustomCalendar className="mt-[3px]" /> | ||
|
||
<div className="flex flex-col"> | ||
<Text typography="text2-medium" color="sub" className="my-[8px]"> | ||
{formatDateKorean(selectedDate, { month: true, day: true })} | ||
</Text> | ||
{dateRecord?.quizRecords.map((record, index) => ( | ||
<RecordItem | ||
key={record.quizSetId + '-' + index} | ||
type={record.quizSetType} | ||
name={record.name} | ||
quizCount={record.quizCount} | ||
score={record.score} | ||
date={dateRecord.solvedDate} | ||
quizSetId={record.quizSetId} | ||
/> | ||
))} | ||
</div> | ||
|
||
<Link href={'/record/all' + `?selectedDate=${selectedDate}`} className="size-fit"> | ||
<Button | ||
variant={'smallSquare'} | ||
colors={'tertiary'} | ||
className="mb-[27px] mt-[8px] h-fit w-full py-[13.5px]" | ||
> | ||
기록 전체보기 | ||
<Icon name="chevron-right" className="size-[16px] text-icon-tertiary" /> | ||
</Button> | ||
</Link> | ||
</main> | ||
) | ||
} | ||
|
||
export default RecordPage |
Oops, something went wrong.