Skip to content

Commit

Permalink
Merge pull request #202 from team-offonoff/feat/b-side-detail-page
Browse files Browse the repository at this point in the history
B 사이드 상세 페이지 구현
  • Loading branch information
Jinho1011 authored Feb 14, 2024
2 parents d7e66db + 3a3c64c commit 360a128
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 8 deletions.
9 changes: 8 additions & 1 deletion src/components/B/BTopicCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';

import CommentChip from '@components/commons/Chip/CommentChip';
import { Col, Row } from '@components/commons/Flex/Flex';
Expand All @@ -17,9 +18,15 @@ interface BTopicCardProps {
}

const BTopicCard = ({ topic }: BTopicCardProps) => {
const navigate = useNavigate();

const handleCardClick = () => {
navigate(`/topics/b/${topic.topicId}`, { state: { topic } });
};

return (
<>
<CardContainer>
<CardContainer onClick={handleCardClick}>
<Col padding={'12px 22px 20px'}>
<Row justifyContent={'space-between'} alignItems={'center'} style={{ marginBottom: 2 }}>
<Row gap={10}>
Expand Down
1 change: 1 addition & 0 deletions src/components/Home/ChoiceSlide/ChoiceSlide.styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const BetaSideContainer = styled(SlideContainer)`

export const TextContainer = styled.div`
z-index: 1;
box-sizing: content-box;
justify-content: flex-start;
width: 87px;
padding: 0 44px;
Expand Down
36 changes: 36 additions & 0 deletions src/components/commons/Header/BackButton/BackButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { styled } from 'styled-components';

import { colors } from '@styles/theme';

import { RightChevronIcon } from '@icons/index';

interface BackButtonProps {
onClick?: () => void;
}

const BackButton = ({ onClick }: BackButtonProps) => {
const navigate = useNavigate();

const handleBackButtonClick = () => {
navigate(-1);
};

return (
<Button onClick={onClick ? onClick : handleBackButtonClick}>
<RightChevronIcon style={{ transform: 'rotate(180deg)' }} stroke={colors.white} />
</Button>
);
};

const Button = styled.button`
display: flex;
align-items: center;
width: 24px;
height: 24px;
padding: 5px;
cursor: pointer;
`;

export default BackButton;
115 changes: 115 additions & 0 deletions src/routes/B/BTopic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import React, { useState } from 'react';
import { useLocation } from 'react-router-dom';

import { useLatestComment } from '@apis/comment/useComment';
import useVoteTopic from '@apis/topic/useVoteTopic';
import BackButton from '@components/commons/Header/BackButton/BackButton';
import Layout from '@components/commons/Layout/Layout';
import ProfileImg from '@components/commons/ProfileImg/ProfileImg';
import Text from '@components/commons/Text/Text';
import ChoiceSlider from '@components/Home/ChoiceSlider/ChoiceSlider';
import CommentBox from '@components/Home/CommentBox/CommentBox';
import Timer from '@components/Home/Timer/Timer';
import {
TopicCardContainer,
BestTopicCotainer,
TopicContainer,
Topic,
UserInfoContainer,
SelectTextContainer,
} from '@components/Home/TopicCard/TopicCard.styles';
import TopicComments from '@components/Home/TopicComments/TopicComments';
import VoteCompletion from '@components/Home/VoteCompletion/VoteCompletion';
import useBottomSheet from '@hooks/useBottomSheet/useBottomSheet';
import { LatestComment } from '@interfaces/api/comment';
import { Choice, TopicResponse } from '@interfaces/api/topic';

import { colors } from '@styles/theme';

import { LeftDoubleArrowIcon, RightDoubleArrowIcon } from '@icons/index';

interface BTopicProps {
topic: TopicResponse;
}

const BTopic = () => {
const location = useLocation();
const { topic } = location.state as BTopicProps;
const { BottomSheet: CommentSheet, toggleSheet } = useBottomSheet({});
const voteMutation = useVoteTopic();
const { data: latestCommentData, isSuccess } = useLatestComment(
topic.topicId,
topic.selectedOption !== null
);
const [latestComment, setLatestComment] = useState<LatestComment | undefined>();

const handleVote = async (choiceOption: Choice['choiceOption']) => {
const data = await voteMutation.mutateAsync({
topicId: topic.topicId,
choiceOption: choiceOption,
votedAt: new Date().getTime() / 1000,
});
setLatestComment(data.latestComment);
};

const handleCommentBoxClick = () => {
if (topic.selectedOption !== null) {
toggleSheet();
}
};

return (
<React.Fragment>
<Layout hasBottomNavigation={false} HeaderLeft={<BackButton />}>
<TopicCardContainer>
<TopicContainer>
<Topic style={{ width: 170, wordBreak: 'keep-all', overflowWrap: 'break-word' }}>
{topic.topicTitle}
</Topic>
</TopicContainer>
<UserInfoContainer>
<ProfileImg url={topic.author.profileImageUrl} size={20} />
<Text size={14} weight={'regular'} color={colors.white_60}>
{topic.author.nickname}
</Text>
</UserInfoContainer>
{topic.selectedOption !== null ? (
<VoteCompletion
side={topic.selectedOption === 'CHOICE_A' ? 'A' : 'B'}
topicContent={
topic.selectedOption === 'CHOICE_A'
? topic.choices[0]?.content?.text || 'A'
: topic.choices[1]?.content?.text || 'B'
}
/>
) : (
<ChoiceSlider onVote={handleVote} choices={topic.choices} />
)}
{topic.deadline && <Timer endTime={topic.deadline} />}
<SelectTextContainer $voted={topic.selectedOption !== null}>
<LeftDoubleArrowIcon />
<Text size={14} weight={'regular'} color={colors.white_40}>
밀어서 선택하기
</Text>
<RightDoubleArrowIcon />
</SelectTextContainer>
<CommentBox
side={topic.topicSide}
hasVoted={topic.selectedOption !== null}
topicId={topic.topicId}
commentCount={0}
voteCount={0}
keyword={topic.keyword}
latestComment={latestComment}
onClick={handleCommentBoxClick}
/>
</TopicCardContainer>
</Layout>
<CommentSheet>
<TopicComments topic={topic} />
</CommentSheet>
</React.Fragment>
);
};

export default BTopic;
12 changes: 5 additions & 7 deletions src/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ import {
createRoutesFromElements,
} from 'react-router-dom';

import Loading from '@components/commons/Loading/Loading';

import { useAuthStore } from '@store/auth';

const Home = lazy(() => import('./Home/Home'));
const ATopics = lazy(() => import('./A/ATopics'));
const BTopic = lazy(() => import('./B/BTopic'));
const BTopics = lazy(() => import('./B/BTopics'));
const TopicSideSelection = lazy(() => import('./Topic/TopicSideSelection'));
const TopicCreate = lazy(() => import('./Topic/Create/TopicCreate'));
Expand All @@ -23,7 +26,6 @@ const Signup = lazy(() => import('./Auth/signup/Signup'));

const AuthRoute = () => {
const reLogin = useAuthStore((store) => store.reLogin);
const [isLoading, setIsLoading] = useState(true);

useLayoutEffect(() => {
const handleReLogin = async () => {
Expand All @@ -32,18 +34,13 @@ const AuthRoute = () => {
} catch (e) {
console.error(e);
}
setIsLoading(false);
};

handleReLogin();
}, []);

if (isLoading) {
return <></>;
}

return (
<Suspense fallback={<div>Loading...</div>}>
<Suspense fallback={<Loading />}>
<Outlet />
</Suspense>
);
Expand All @@ -68,6 +65,7 @@ const Router = () => {
<Route path="topics">
<Route path="a" element={<ATopics />} />
<Route path="b" element={<BTopics />} />
<Route path="b/:topicId" element={<BTopic />} />
<Route path="create" element={<TopicSideSelection />} />
<Route path="create/:topicSide" element={<TopicCreate />} />
</Route>
Expand Down

0 comments on commit 360a128

Please sign in to comment.