From 582a259cc34205e7cb772241a44eb89e909051f4 Mon Sep 17 00:00:00 2001 From: Jeon Jinho Date: Thu, 7 Mar 2024 15:41:39 +0900 Subject: [PATCH] =?UTF-8?q?A=20=EC=82=AC=EC=9D=B4=EB=93=9C=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EC=B9=A9=20=EC=B6=94=EA=B0=80=20(#236)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add icons * feat: add useTrendingTopics * fix: add icon to replace dot in Chip component --- src/apis/topic/useTopics.ts | 14 ++++++++- src/assets/icons/hot.svg | 20 +++++++++++++ src/assets/icons/index.ts | 4 +++ src/assets/icons/trending.svg | 12 ++++++++ src/components/A/ATopicCard.tsx | 24 ++++++++++------ src/components/commons/Chip/Chip.tsx | 23 ++++----------- src/routes/A/ATopics.tsx | 43 ++++++++++++---------------- 7 files changed, 87 insertions(+), 53 deletions(-) create mode 100644 src/assets/icons/hot.svg create mode 100644 src/assets/icons/trending.svg diff --git a/src/apis/topic/useTopics.ts b/src/apis/topic/useTopics.ts index 0a10e4f..bc3a14c 100644 --- a/src/apis/topic/useTopics.ts +++ b/src/apis/topic/useTopics.ts @@ -35,6 +35,10 @@ const useTopics = (req?: TopicsRequestDTO) => { }); }; +const useTrendingTopics = () => { + return useTopics({ status: 'VOTING', sort: 'voteCount,DESC', page: 0, size: 3, side: 'TOPIC_A' }); +}; + const createTopics = (req: TopicCreateRequestDTO) => { return client.post({ path: `/topics`, @@ -61,4 +65,12 @@ const useGetPresignedURL = () => { export default useTopics; -export { useCreateTopics, useGetPresignedURL }; +export { + getTopics, + useTopics, + useTrendingTopics, + createTopics, + getPresignedURL, + useCreateTopics, + useGetPresignedURL, +}; diff --git a/src/assets/icons/hot.svg b/src/assets/icons/hot.svg new file mode 100644 index 0000000..3692f62 --- /dev/null +++ b/src/assets/icons/hot.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/icons/index.ts b/src/assets/icons/index.ts index ab9266a..212a2a7 100644 --- a/src/assets/icons/index.ts +++ b/src/assets/icons/index.ts @@ -27,6 +27,7 @@ import HideIcon from './hide.svg?react'; import HitIcon from './hit.svg?react'; import HomeStrokeIcon from './home-stroke.svg?react'; import HomeIcon from './home.svg?react'; +import HotIcon from './hot.svg?react'; import SelectedImageIcon from './image-icon-selected.svg?react'; import ImageIcon from './image-icon.svg?react'; import KakaoIcon from './kakao.svg?react'; @@ -47,6 +48,7 @@ import ThumbsIcon from './thumbs.svg?react'; import TopicCreatBackgrounIcon from './topic-create-background.svg?react'; import TrashCanIcon from './trash-can.svg?react'; import TrashIcon from './trash.svg?react'; +import TrendingIcon from './trending.svg?react'; import UpDownChevronIcon from './up-down.svg?react'; import WriteBoxIcon from './write-box.svg?react'; @@ -73,6 +75,7 @@ export { HideIcon, HitIcon, HomeIcon, + HotIcon, HomeStrokeIcon, KakaoIcon, LeftDoubleArrowIcon, @@ -98,6 +101,7 @@ export { SelectedImageIcon, DeleteIcon, TrashIcon, + TrendingIcon, AlbumIcon, CameraIcon, DotIcon, diff --git a/src/assets/icons/trending.svg b/src/assets/icons/trending.svg new file mode 100644 index 0000000..4f9d6ba --- /dev/null +++ b/src/assets/icons/trending.svg @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/components/A/ATopicCard.tsx b/src/components/A/ATopicCard.tsx index 7f2a039..68df0d4 100644 --- a/src/components/A/ATopicCard.tsx +++ b/src/components/A/ATopicCard.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import useVoteTopic from '@apis/topic/useVoteTopic'; import Chip from '@components/commons/Chip/Chip'; import CommentChip from '@components/commons/Chip/CommentChip'; import { Col, Row } from '@components/commons/Flex/Flex'; @@ -12,21 +11,23 @@ import { TopicResponse } from '@interfaces/api/topic'; import { colors } from '@styles/theme'; -import { MeatballIcon } from '@icons/index'; +import { HotIcon, MeatballIcon, TrendingIcon } from '@icons/index'; import { getDateDiff } from '@utils/date'; interface AlphaTopicCardProps { topic: TopicResponse; onVote: (topicId: number, side: 'CHOICE_A' | 'CHOICE_B') => void; - chip?: 'popular' | 'close'; + isTrending?: boolean; } -const AlphaTopicCard = React.memo(({ topic, onVote, chip }: AlphaTopicCardProps) => { +const AlphaTopicCard = React.memo(({ topic, onVote, isTrending }: AlphaTopicCardProps) => { const { BottomSheet: CommentSheet, toggleSheet } = useBottomSheet({}); const [A, B] = topic.choices; const roundedPercentageA = Math.round((A.voteCount / topic.voteCount) * 100); const roundedPercentageB = 100 - roundedPercentageA; + const isHot = 45 < roundedPercentageA && roundedPercentageA < 55; + const hasChip = isTrending || isHot; const handleCommentChipClick = () => { toggleSheet(); @@ -38,22 +39,27 @@ const AlphaTopicCard = React.memo(({ topic, onVote, chip }: AlphaTopicCardProps) const handleOptionClick = () => {}; + const TrendingChip = () => ( + } tintColor={'#8CFF8A'} label={'실시간 인기 토픽'} /> + ); + const HotChip = () => } tintColor={'#FF61B7'} label={'치열한 경쟁 중'} />; + const TopicCardChip = () => (isTrending ? : isHot ? : null); + return ( <> - {chip && ( + {hasChip && ( - + )} {topic.topicTitle} - {/* TBD: 1차 스펙 아웃 */} - {/* */} + { +const Chip = ({ icon, tintColor, label }: ChipProps) => { return ( - + {icon} {label} @@ -19,29 +20,15 @@ const Chip = ({ tintColor, label }: ChipProps) => { ); }; -const Dot = styled.div<{ color: string }>` - width: 14px; - height: 14px; - background-color: ${({ color }) => color}; - border-radius: 50%; -`; - const Container = styled.button<{ color: string }>` display: flex; - gap: 10px; + gap: 4px; align-items: center; justify-content: center; width: fit-content; padding: 2px 10px; background-color: ${({ color }) => { - const hexToRgb = (hex: string) => { - const r = parseInt(hex.slice(1, 3), 16), - g = parseInt(hex.slice(3, 5), 16), - b = parseInt(hex.slice(5, 7), 16); - return [r, g, b]; - }; - const [r, g, b] = hexToRgb(color); - return `rgba(${r}, ${g}, ${b}, 0.2)`; + return `${color}33`; }}; border-radius: 20px; `; diff --git a/src/routes/A/ATopics.tsx b/src/routes/A/ATopics.tsx index 3ca536a..b14da01 100644 --- a/src/routes/A/ATopics.tsx +++ b/src/routes/A/ATopics.tsx @@ -1,13 +1,12 @@ -import { ChangeEvent, useState } from 'react'; +import { useState } from 'react'; -import useTopics from '@apis/topic/useTopics'; +import useTopics, { useTrendingTopics } from '@apis/topic/useTopics'; import useVoteTopic from '@apis/topic/useVoteTopic'; import ATopicCard from '@components/A/ATopicCard'; import { Col, Row } from '@components/commons/Flex/Flex'; import Layout from '@components/commons/Layout/Layout'; import Text from '@components/commons/Text/Text'; import { Toast } from '@components/commons/Toast/Toast'; -import ToggleSwitch from '@components/commons/ToggleSwitch/ToggleSwitch'; import { colors } from '@styles/theme'; @@ -18,17 +17,15 @@ import { ResponseError } from '@apis/fetch'; import { Container } from './ATopics.styles'; const ATopics = () => { - const { data } = useTopics({ side: 'TOPIC_A', sort: 'createdAt,DESC' }); + const { data: topicPages } = useTopics({ side: 'TOPIC_A', sort: 'createdAt,DESC' }); + const { data: trendingTopicPages } = useTrendingTopics(); + const voteMutation = useVoteTopic({ side: 'TOPIC_A', sort: 'createdAt,DESC' }); - // const [topicFilter, setTopicFilter] = useState('진행중'); const [isMineOnly, setIsMineOnly] = useState(false); const [isLatest, setIsLatest] = useState(true); - const topics = data?.pages.flatMap((page) => page.data); - - // const handleTopicStatusChange = (e: ChangeEvent) => { - // setTopicFilter(e.target.value); - // }; + const topics = topicPages?.pages.flatMap((page) => page.data); + const trendingTopics = trendingTopicPages?.pages.flatMap((page) => page.data); const handleVote = async (topicId: number, side: 'CHOICE_A' | 'CHOICE_B') => { try { @@ -48,20 +45,6 @@ const ATopics = () => { } - // HeaderCenter={ - // - // - // - // 진행중 - // - // - // - // - // 종료된 - // - // - // - // } > @@ -92,7 +75,17 @@ const ATopics = () => { {topics?.map((topic) => { - return ; + const isTrending = trendingTopics?.some( + (trendingTopic) => trendingTopic.topicId === topic.topicId + ); + return ( + + ); })}