Skip to content

Commit

Permalink
feat(toks-main, quiz): 퀴즈 카드 리팩토링 (#406)
Browse files Browse the repository at this point in the history
* refactor: 메인카드 리스트 리팩토링

* refactor: 캐러셀 카드 수정 및 적용

* fix: badge 위치 수정

* fix: mobile break point를 통한 캐러셀 깨짐방지

* fix: quiztypo

* fix: card 최소너비 수정 및 정책정하기

* fix: 캐러셀 사이즈 재구성 및 구현

* 퀴즈 카드 OX썸네일 대응

* feat: 퀴즈 상세 카테고리 색상 변경

---------

Co-authored-by: minsgy <[email protected]>
Co-authored-by: dengoyoon <[email protected]>
  • Loading branch information
3 people authored Feb 24, 2024
1 parent 5b70297 commit f126825
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 128 deletions.
17 changes: 6 additions & 11 deletions src/app/quiz/[quizId]/@detail/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from '@/app/quiz/hooks/';
import { OX, QuizButtonType } from '@/app/quiz/models/quiz';
import { Text, bgColor } from '@/common';
// import { Badge } from '@/common/components/Badge';

type Props = {
params: {
Expand All @@ -30,7 +31,6 @@ function DetailPage({ params: { quizId } }: Props) {

const {
quizTitle,
tags,
oxImageUrl,
buttonLeft,
buttonRight,
Expand All @@ -57,16 +57,11 @@ function DetailPage({ params: { quizId } }: Props) {
<section
className={clsx(bgColor['gray110'], 'mt-8px rounded-16px p-20px')}
>
<div className="flex gap-8px">
{[categoryName, ...tags].map((tagName, index) => (
<Text
key={`${tagName}-${index}`}
typo="captionBold"
color="primaryDefault"
>
{tagName}
</Text>
))}
<div className="flex items-center gap-[4px]">
{/* <Badge label={checkSameQuizType('A_B_') ? 'AB' : 'OX'} /> */}
<Text typo="captionBold" color="gray60">
{categoryName}
</Text>
</div>
<Text className="mt-12px block " typo="headingL" color="gray10">
{quizTitle}
Expand Down
31 changes: 15 additions & 16 deletions src/app/quiz/components/QuizCarousel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { useRouter } from 'next/navigation';
import SwiperCore from 'swiper';
import { Swiper, SwiperSlide } from 'swiper/react';

import { QuizCard } from '@/common';

import 'swiper/css';
import { CarouselCard } from '@/common/components/CarouselCard';

import { QuizCarouselProps } from './type';

export function QuizCarousel({
Expand All @@ -17,7 +17,17 @@ export function QuizCarousel({

const settings: SwiperCore = {
spaceBetween: 8,
slidesPerView: 1.03,
slidesPerView: 1.1,

breakpoints: {
420: {
slidesPerView: 1.2,
},

440: {
slidesPerView: 1.3,
},
},
};

const recommendQuizzes = quizRecommendModels.map(
Expand All @@ -36,23 +46,12 @@ export function QuizCarousel({
<div className={className}>
<Swiper className="!important -mx-20px px-20px" {...settings}>
{recommendQuizzes.map(
({
quizId,
tags,
quizDescription,
image,
quizReplyHistoryCount,
quizCommentCount,
quizType,
}) => (
({ quizId, tags, quizDescription, image, quizType }) => (
<SwiperSlide key={quizId}>
<QuizCard
<CarouselCard
categoryTitle={tags.join(' ')}
quizDescription={quizDescription}
images={image ? [image] : []}
sizeType="small"
likeCount={quizReplyHistoryCount}
commentCount={quizCommentCount}
quizType={quizType.startsWith('A_B_') ? 'default' : 'ox'}
handleCardClick={() => router.push(`/quiz/${quizId}`)}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/app/toks-main/components/CardList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const CardList = () => {
}

return (
<div className="flex h-full flex-col gap-8px">
<div className="flex h-full flex-col gap-24px">
{quizList?.length === 0 && (
<div className="flex h-main items-center justify-center">
<QuizNotice />
Expand Down
13 changes: 13 additions & 0 deletions src/common/components/Badge/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';

import { Text } from '../Text';

export const Badge = ({ label }: { label: string }) => {
return (
<div className="inline-flex items-center justify-center rounded-[4px] bg-gray-110 px-[4px] pb-[2px] pt-[3px]">
<Text typo="captionBold" color="white">
{label}
</Text>
</div>
);
};
88 changes: 88 additions & 0 deletions src/common/components/CarouselCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import clsx from 'clsx';
import Image from 'next/image';
import React from 'react';

import { ICON_URL } from '@/common/constants';

import { Badge } from './Badge';
import { QuizCardProps } from './QuizCard/types';
import { Text } from './Text';

export const CarouselCard = ({
categoryTitle,
quizDescription,
images,
quizType = 'default',
handleCardClick,
}: Omit<QuizCardProps, 'sizeType' | 'commentCount' | 'likeCount'>) => {
const isOX = quizType === 'ox';
const OxQuizThumbnail = () => {
return (
<div className="flex h-full w-full rounded-8px">
<div
className="flex flex-1 items-center justify-center"
style={{
backgroundColor: '#3E97FF',
}}
>
<Image src={ICON_URL.O} alt="OX 퀴즈 O" width={26} height={26} />
</div>
<div
className="flex flex-1 items-center justify-center"
style={{
backgroundColor: '#FF5B65',
}}
>
<Image src={ICON_URL.X} alt="OX 퀴즈 X" width={22} height={22} />
</div>
</div>
);
};

return (
<div
role="button"
onClick={handleCardClick}
className={clsx(
'flex min-w-246px max-w-320px justify-between gap-16px rounded-12px bg-gray-90 p-20px'
)}
>
<div className="flex w-full flex-1 flex-col">
<div className="flex items-center gap-[4px]">
<Badge label={quizType === 'default' ? 'AB' : 'OX'} />
<Text typo="captionBold" color="gray60">
{categoryTitle}
</Text>
</div>
<div className="inline-flex flex-1 -translate-y-0.5 items-center pt-8px">
<Text className="line-clamp-3" typo="subheadingBold" color="gray10">
{quizDescription}
</Text>
</div>
</div>
<div className="flex h-100px w-100px flex-col justify-between overflow-hidden rounded-8px">
{isOX && images?.length === 0 ? (
<OxQuizThumbnail />
) : (
images?.map((src, index) => (
<div
className={images.length > 1 ? 'h-1/2' : 'h-full'}
key={`${src}-${index}`}
>
<img
className="h-full w-full"
src={src}
alt={src}
loading="lazy"
style={{
objectFit: 'cover',
objectPosition: 'center',
}}
/>
</div>
))
)}
</div>
</div>
);
};
139 changes: 39 additions & 100 deletions src/common/components/QuizCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,38 @@ import clsx from 'clsx';
import Image from 'next/image';
import React from 'react';

import { ICON_URL } from '@/common/constants';

import type { QuizCardProps } from './types';
import { Badge } from '../Badge';
import { Text } from '../Text';

export const QuizCard = ({
categoryTitle,
quizDescription,
images,
likeCount = 0,
commentCount = 0,
sizeType = 'large',
quizType = 'default',
handleCardClick,
}: QuizCardProps) => {
const isSmall = sizeType === 'small';
const isOX = quizType === 'ox';

const OxQuizThumbnail = () => {
if (isSmall) {
return (
<div className="flex h-full w-full rounded-8px">
<div
className="flex flex-1 items-center justify-center"
style={{
backgroundColor: '#3E97FF',
}}
>
<Image src={ICON_URL.O} alt="OX 퀴즈 O" width={24} height={24} />
</div>
<div
className="flex flex-1 items-center justify-center"
style={{
backgroundColor: '#FF5B65',
}}
>
<Image src={ICON_URL.X} alt="OX 퀴즈 X" width={22} height={22} />
</div>
</div>
);
}

return (
<div className="flex h-full w-full flex-col gap-8px">
<div
className="relative flex flex-1 items-center justify-center rounded-8px"
style={{
backgroundColor: '#3E97FF',
}}
>
<div className="flex h-full flex-1">
<div className="relative flex flex-1 items-center justify-center bg-blue-10">
<Image
width={73}
height={73}
src="https://asset.tokstudy.com/ic_O.svg"
alt="OX 퀴즈 O"
width={38}
height={38}
loading="lazy"
/>
</div>
<div
className="relative flex flex-1 items-center justify-center rounded-8px"
style={{
backgroundColor: '#FF5B65',
}}
>
<div className="relative flex flex-1 items-center justify-center bg-danger-default">
<Image
width={73}
height={73}
src="https://asset.tokstudy.com/ic_X.svg"
alt="OX 퀴즈 X"
width={36}
height={36}
loading="lazy"
/>
</div>
</div>
Expand All @@ -80,65 +44,40 @@ export const QuizCard = ({
role="button"
onClick={handleCardClick}
className={clsx(
'flex w-full min-w-180px justify-between gap-20px rounded-12px bg-gray-110 px-16px py-20px',
isSmall ? 'h-160px' : 'h-220px'
'flex h-fit w-full min-w-180px flex-col justify-between gap-20px overflow-hidden rounded-12px bg-gray-110'
)}
>
<div className="flex w-full flex-1 flex-col">
<Text
className="inline-block"
typo="captionBold"
color="primaryDefault"
>
{categoryTitle}
</Text>
<div className="inline-flex flex-1 -translate-y-0.5 items-center pt-12px">
<Text
className="line-clamp-3"
typo={isSmall ? 'subheadingBold' : 'headingM'}
color="gray10"
>
{quizDescription}
</Text>
<div className="flex h-full w-full flex-col justify-between overflow-hidden rounded-8px">
<div className="flex h-[167px] w-full">
{isOX && images?.length === 0 ? (
<OxQuizThumbnail />
) : (
images?.map((src, index) => (
<div className="h-full flex-1" key={`${src}-${index}`}>
<img
className="h-full w-full object-cover object-center"
src={src}
alt={src}
loading="lazy"
/>
</div>
))
)}
</div>
<div className="flex gap-8px">
<Text typo="caption" color="gray50">
🔥 참여 {likeCount}
</Text>
<Text typo="caption" color="gray50">
💬 댓글 {commentCount}
</Text>
<div className="flex w-full flex-1 flex-col bg-gray-90 p-[16px]">
<div className="flex items-center gap-[4px]">
<Badge label={quizType === 'default' ? 'AB' : 'OX'} />
<Text typo="captionBold" color="gray60">
{categoryTitle}
</Text>
</div>
<div className="inline-flex flex-1 -translate-y-0.5 items-center pt-12px">
<Text className="line-clamp-2" typo="bodyBold" color="gray10">
{quizDescription}
</Text>
</div>
</div>
</div>
<div className="flex h-full w-120px flex-col justify-between overflow-hidden rounded-8px">
{isOX && images?.length === 0 ? (
<OxQuizThumbnail />
) : (
images?.map((src, index) => (
<div
className={images.length > 1 ? 'h-1/2' : 'h-full'}
key={`${src}-${index}`}
>
<img
className="h-full w-full"
src={src}
alt={src}
loading="lazy"
// fill={true}
style={{
objectFit: 'cover',
objectPosition: 'center',
}}
// layout="fill"
// objectFit="cover"
// objectPosition="center"
// placeholder="blur"
// blurDataURL={ICON_URL.BLUR_BACKGROUND}
/>
</div>
))
)}
</div>
</div>
);
};

0 comments on commit f126825

Please sign in to comment.