Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FE] feature/#301 내 정보 페이지 구현 #309

Merged
merged 8 commits into from
Aug 16, 2023
2 changes: 1 addition & 1 deletion frontend/src/assets/InfoDefalutImg.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 23 additions & 2 deletions frontend/src/components/Layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Navbar from './Navbar';
import Back from '../../assets/Back.svg';
import ModalProvider from '../../context/ModalContext';
import NavbarHighlightsProvider from '../../context/NavbarHighlightsContext';
import InfoDefalutImg from '../../assets/InfoDefalutImg.svg';

type LayoutProps = {
children: React.ReactNode;
Expand All @@ -30,6 +31,12 @@ const Layout = ({ children }: LayoutProps) => {
const { Tmapv3 } = window;
const mapContainer = useRef(null);
const { width } = useContext(LayoutWidthContext);
const isLogined = localStorage.getItem('userToken');
const user = JSON.parse(localStorage.getItem('user') || '');

const loginButtonClick = () => {
window.location.href = 'https://mapbefine.kro.kr/api/oauth/kakao';
};

const [map, setMap] = useState(null);

Expand Down Expand Up @@ -58,9 +65,16 @@ const Layout = ({ children }: LayoutProps) => {
height="100vh"
$backgroundColor="white"
>
<Flex $flexDirection="column" padding="20px 20px 0 20px">
<Flex
$justifyContent="space-between"
padding="20px 20px 0 20px"
>
<Logo />
<Space size={4} />
{isLogined ? (
<MyInfoImg src={user.imageUrl} />
) : (
<InfoDefalutImg onClick={loginButtonClick} />
)}
</Flex>
<Flex
height="calc(100vh - 40px)"
Expand Down Expand Up @@ -88,4 +102,11 @@ const LayoutFlex = styled(Flex)`
transition: all ease 0.3s;
`;

const MyInfoImg = styled.img`
width: 40px;
height: 40px;

border-radius: 50%;
`;

export default Layout;
17 changes: 3 additions & 14 deletions frontend/src/components/MyInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const MyInfo = () => {
name: 'Patrick',
email: '[email protected]',
});
const user = JSON.parse(localStorage.getItem('user') || '');

// useEffect(()=>{
// setMyInfoName()
Expand Down Expand Up @@ -44,11 +45,7 @@ const MyInfo = () => {
$justifyContent="center"
$alignItems="center"
>
{isThereImg ? (
<MyInfoImg src="https://images.unsplash.com/photo-1480429370139-e0132c086e2a?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=988&q=80" />
) : (
<InfoDefalutImg />
)}
<MyInfoImg src={user.imageUrl} />
<Space size={7} />
<Box>
<Text color="black" $fontSize="default" $fontWeight="normal">
Expand All @@ -58,14 +55,12 @@ const MyInfo = () => {
{myInfoNameAndEmail.email}
</Text>
</Box>
<MyInfoModifyIcon>
<ModifyMyInfoIcon onClick={onModifyInfo} />
</MyInfoModifyIcon>
</MyInfoContainer>
);
};

const MyInfoContainer = styled(Flex)`
position: relative;
border: 1px solid ${({ theme }) => theme.color.lightGray};
`;

Expand All @@ -76,10 +71,4 @@ const MyInfoImg = styled.img`
border-radius: 50%;
`;

const MyInfoModifyIcon = styled(Box)`
position: absolute;
right: 32px;
top: 32px;
`;

export default MyInfo;
50 changes: 50 additions & 0 deletions frontend/src/components/MyInfoContainer/MyInfoList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Fragment, useEffect, useState } from 'react';
import { styled } from 'styled-components';
import { getApi } from '../../../apis/getApi';
import { MyInfoPinType, MyInfoTopicType } from '../../../types/MyInfo';
import PinCard from '../../PinCard';
import TopicCard from '../../TopicCard';

const MyInfoList = () => {
const [myInfoTopics, setMyInfoTopics] = useState<MyInfoTopicType[]>([]);

const getMyInfoListFromServer = async () => {
const serverMyInfoTopics = await getApi<MyInfoTopicType[]>(
'default',
'/members/my/topics',
);
setMyInfoTopics(serverMyInfoTopics);
};

useEffect(() => {
getMyInfoListFromServer();
}, []);

if (!myInfoTopics) return <></>;

return (
<MyInfoListWrapper>
{myInfoTopics.map((topic, index) => {
return (
<Fragment key={topic.id}>
<TopicCard
topicId={topic.id}
topicImage={topic.image}
topicTitle={topic.name}
topicUpdatedAt={topic.updatedAt}
topicPinCount={topic.pinCount}
/>
</Fragment>
);
})}
</MyInfoListWrapper>
);
};

const MyInfoListWrapper = styled.ul`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

멘틱멘틱 시멘틱 굳~~ 👍👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우하핳 😆

display: grid;
grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
grid-row-gap: ${({ theme }) => theme.spacing[5]};
`;

export default MyInfoList;
55 changes: 55 additions & 0 deletions frontend/src/components/MyInfoContainer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { styled } from 'styled-components';
import Flex from '../common/Flex';
import Text from '../common/Text';
import Box from '../common/Box';
import Space from '../common/Space';
import { lazy, Suspense } from 'react';
import TopicCardListSeleton from '../TopicCardList/TopicCardListSeleton';
import Button from '../common/Button';
import MyInfoList from './MyInfoList';

interface MyInfoContainerProps {
containerTitle: string;
containerDescription: string;
}

const MyInfoContainer = ({
containerTitle,
containerDescription,
}: MyInfoContainerProps) => (
<section>
<Flex $justifyContent="space-between" $alignItems="flex-end">
<Box>
<Text
color="black"
$fontSize="extraLarge"
$fontWeight="bold"
tabIndex={0}
>
{containerTitle}
</Text>
<Space size={0} />
<Text
color="gray"
$fontSize="default"
$fontWeight="normal"
tabIndex={1}
>
{containerDescription}
</Text>
</Box>
</Flex>

<Space size={4} />

<Suspense fallback={<TopicCardListSeleton />}>
<MyInfoList />
</Suspense>
</section>
);

const SeeAllButton = styled(Button)`
cursor: pointer;
`;

export default MyInfoContainer;
8 changes: 7 additions & 1 deletion frontend/src/components/NotFound/LoginError.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import Space from '../common/Space';
import Text from '../common/Text';

const LoginError = () => {
const loginButtonClick = () => {
window.location.href = 'https://mapbefine.kro.kr/api/oauth/kakao';
};

return (
<Flex
$flexDirection="column"
Expand All @@ -25,7 +29,9 @@ const LoginError = () => {
나만의 지도를 만들어 보세요.
</Text>
<Space size={5} />
<NotFoundButton variant="primary">카카오로 시작하기</NotFoundButton>
<NotFoundButton variant="primary" onClick={loginButtonClick}>
카카오로 시작하기
</NotFoundButton>
</Flex>
</Flex>
);
Expand Down
68 changes: 68 additions & 0 deletions frontend/src/components/PinCard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { styled } from 'styled-components';
import Text from '../common/Text';
import useNavigator from '../../hooks/useNavigator';
import Box from '../common/Box';
import Image from '../common/Image';
import { SyntheticEvent } from 'react';
import Space from '../common/Space';
import Flex from '../common/Flex';
import FavoriteSVG from '../../assets/favoriteBtn_filled.svg';
import SeeTogetherSVG from '../../assets/seeTogetherBtn_filled.svg';
import SmallTopicPin from '../../assets/smallTopicPin.svg';
import SmallTopicStar from '../../assets/smallTopicStar.svg';
import { DEFAULT_TOPIC_IMAGE } from '../../constants';
import AddSeeTogether from '../AddSeeTogether';
import AddFavorite from '../AddFavorite';

export interface PinCardProps {
pinId: number;
pinTitle: string;
pinAddress: string;
pinDescription: string;
}

const PinCard = ({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 새롭게 만든 핀카드??!!! 8시간 뒤가 기대되는군요 ⏰ 설레서 잠을 못 이루겠네요..

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

하하핳... 그냥 토픽 카드에서 이미지 지운 버전이라..

pinId,
pinTitle,
pinAddress,
pinDescription,
}: PinCardProps) => {
const { routePage } = useNavigator();

return (
<Wrapper>
<Flex position="relative">
<Box width="192px" padding={1}>
<Box height="52px">
<Text color="black" $fontSize="default" $fontWeight="bold">
{pinTitle}
</Text>
</Box>

<Space size={0} />

<Text color="gray" $fontSize="small" $fontWeight="normal">
{pinAddress}
</Text>

<Space size={0} />
<Text color="gray" $fontSize="small" $fontWeight="normal">
{pinDescription}
</Text>
</Box>
</Flex>
</Wrapper>
);
};

const Wrapper = styled.li`
width: 332px;
height: 140px;
cursor: pointer;
border: 1px solid ${({ theme }) => theme.color.gray};
border-radius: ${({ theme }) => theme.radius.small};

margin: 0 auto;
`;

export default PinCard;
36 changes: 34 additions & 2 deletions frontend/src/pages/Profile.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,41 @@
import { useState } from 'react';
import { styled } from 'styled-components';
import Box from '../components/common/Box';
import Flex from '../components/common/Flex';
import Space from '../components/common/Space';
import MyInfo from '../components/MyInfo';
import MyInfoContainer from '../components/MyInfoContainer';
import useNavigator from '../hooks/useNavigator';
import useSetNavbarHighlight from '../hooks/useSetNavbarHighlight';

const Profile = () => {
const { navbarHighlights: _ } = useSetNavbarHighlight('profile');
const { routePage } = useNavigator();
const { navbarHighlights: __ } = useSetNavbarHighlight('profile');

return <div>profile</div>;
const goToPopularTopics = () => {
routePage('/see-all/popularity');
};

return (
<ProfileWrapper>
<MyInfoWrapper $justifyContent="center" $alignItems="center">
<MyInfo />
</MyInfoWrapper>
<Space size={6} />
<MyInfoContainer
containerTitle="나의 지도"
containerDescription="내가 만든 지도를 확인해보세요"
/>
</ProfileWrapper>
);
};

const ProfileWrapper = styled(Box)`
width: 70vw;
margin: 0 auto;
`;

const MyInfoWrapper = styled(Flex)`
margin-top: ${({ theme }) => theme.spacing[6]};
`;
export default Profile;
5 changes: 3 additions & 2 deletions frontend/src/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import SeeAllNearTopics from './pages/SeeAllNearTopics';
import SeeAllLatestTopics from './pages/SeeAllLatestTopics';
import SeeTogetherTopics from './pages/SeeTogetherTopics';
import Favorite from './pages/Favorite';
import Profile from './pages/Profile';
import KakaoRedirectPage from './pages/KaKaoRedirectPage';
import ErrorPage from './pages/ErrorPage';
import AskLoginPage from './pages/AskLoginPage';
import { ReactNode } from 'react';
import AuthLayout from './components/Layout/AuthLayout';
import NotFound from './components/NotFound';
import Profile from './pages/Profile';
import LoginError from './components/NotFound/LoginError';
import Bookmark from './pages/Bookmark';

interface routeElement {
Expand Down Expand Up @@ -92,7 +93,7 @@ const routes: routeElement[] = [
},
{
path: '/askLogin',
element: <AskLoginPage />,
element: <LoginError />,
withAuth: false,
},
],
Expand Down
19 changes: 19 additions & 0 deletions frontend/src/types/MyInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,22 @@ export interface MyInfoType {
name: string;
email: string;
}

export interface MyInfoTopicType {
id: number;
name: string;
image: string;
pinCount: number;
bookmarkCount: number;
isBookmarked: boolean;
updatedAt: string;
}

export interface MyInfoPinType {
id: number;
name: string;
address: string;
description: string;
latitude: number;
longitude: number;
}
Loading