Skip to content

Commit

Permalink
A 사이드 화면 칩 추가 (#236)
Browse files Browse the repository at this point in the history
* feat: add icons

* feat: add useTrendingTopics

* fix: add icon to replace dot in Chip component
  • Loading branch information
Jinho1011 authored Mar 7, 2024
1 parent 3dee843 commit 582a259
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 53 deletions.
14 changes: 13 additions & 1 deletion src/apis/topic/useTopics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`,
Expand All @@ -61,4 +65,12 @@ const useGetPresignedURL = () => {

export default useTopics;

export { useCreateTopics, useGetPresignedURL };
export {
getTopics,
useTopics,
useTrendingTopics,
createTopics,
getPresignedURL,
useCreateTopics,
useGetPresignedURL,
};
20 changes: 20 additions & 0 deletions src/assets/icons/hot.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';

Expand All @@ -73,6 +75,7 @@ export {
HideIcon,
HitIcon,
HomeIcon,
HotIcon,
HomeStrokeIcon,
KakaoIcon,
LeftDoubleArrowIcon,
Expand All @@ -98,6 +101,7 @@ export {
SelectedImageIcon,
DeleteIcon,
TrashIcon,
TrendingIcon,
AlbumIcon,
CameraIcon,
DotIcon,
Expand Down
12 changes: 12 additions & 0 deletions src/assets/icons/trending.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 15 additions & 9 deletions src/components/A/ATopicCard.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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();
Expand All @@ -38,22 +39,27 @@ const AlphaTopicCard = React.memo(({ topic, onVote, chip }: AlphaTopicCardProps)

const handleOptionClick = () => {};

const TrendingChip = () => (
<Chip icon={<TrendingIcon />} tintColor={'#8CFF8A'} label={'실시간 인기 토픽'} />
);
const HotChip = () => <Chip icon={<HotIcon />} tintColor={'#FF61B7'} label={'치열한 경쟁 중'} />;
const TopicCardChip = () => (isTrending ? <TrendingChip /> : isHot ? <HotChip /> : null);

return (
<>
<Col padding={'20px'}>
{chip && (
{hasChip && (
<Row style={{ marginBottom: 12 }}>
<Chip tintColor={'#D3FF9C'} label={'실시간 인기 토픽'} />
<TopicCardChip />
</Row>
)}
<Row justifyContent={'space-between'} style={{ marginBottom: 14 }}>
<Text size={18} weight={500} color={colors.white}>
{topic.topicTitle}
</Text>
{/* TBD: 1차 스펙 아웃 */}
{/* <button onClick={handleOptionClick}>
<button onClick={handleOptionClick}>
<MeatballIcon fill={colors.white_60} />
</button> */}
</button>
</Row>
<Col gap={5} style={{ marginBottom: 14 }}>
<ProgressBar
Expand Down
23 changes: 5 additions & 18 deletions src/components/commons/Chip/Chip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,31 @@ import { styled } from 'styled-components';
import Text from '../Text/Text';

interface ChipProps {
icon: React.ReactNode;
tintColor: string;
label: string;
}

const Chip = ({ tintColor, label }: ChipProps) => {
const Chip = ({ icon, tintColor, label }: ChipProps) => {
return (
<Container color={tintColor}>
<Dot color={tintColor} />
{icon}
<Text size={13} weight={600} color={tintColor}>
{label}
</Text>
</Container>
);
};

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;
`;
Expand Down
43 changes: 18 additions & 25 deletions src/routes/A/ATopics.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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<HTMLInputElement>) => {
// 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 {
Expand All @@ -48,20 +45,6 @@ const ATopics = () => {
<Layout
hasBottomNavigation
HeaderLeft={<ALogoIcon width={30} height={30} fill={colors.white} />}
// HeaderCenter={
// <ToggleSwitch value={topicFilter} onChange={handleTopicStatusChange}>
// <ToggleSwitch.Option value={'진행중'}>
// <Text size={15} weight={500} color={'inherit'}>
// 진행중
// </Text>
// </ToggleSwitch.Option>
// <ToggleSwitch.Option value={'종료된'}>
// <Text size={15} weight={500} color={'inherit'}>
// 종료된
// </Text>
// </ToggleSwitch.Option>
// </ToggleSwitch>
// }
>
<Container>
<Row justifyContent={'flex-end'} gap={12} padding="15px 20px">
Expand Down Expand Up @@ -92,7 +75,17 @@ const ATopics = () => {
</Row>
<Col style={{ backgroundColor: 'inherit', paddingBottom: 100 }}>
{topics?.map((topic) => {
return <ATopicCard key={topic.topicId} topic={topic} onVote={handleVote} />;
const isTrending = trendingTopics?.some(
(trendingTopic) => trendingTopic.topicId === topic.topicId
);
return (
<ATopicCard
key={topic.topicId}
topic={topic}
onVote={handleVote}
isTrending={isTrending}
/>
);
})}
</Col>
</Container>
Expand Down

0 comments on commit 582a259

Please sign in to comment.