diff --git a/frontend/src/assets/InfoDefalutImg.svg b/frontend/src/assets/InfoDefalutImg.svg index 6c7f9a2ee..edafb60a9 100644 --- a/frontend/src/assets/InfoDefalutImg.svg +++ b/frontend/src/assets/InfoDefalutImg.svg @@ -1,4 +1,4 @@ - + diff --git a/frontend/src/components/Layout/index.tsx b/frontend/src/components/Layout/index.tsx index 66a92ea39..9d39e1ade 100644 --- a/frontend/src/components/Layout/index.tsx +++ b/frontend/src/components/Layout/index.tsx @@ -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; @@ -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); @@ -58,9 +65,16 @@ const Layout = ({ children }: LayoutProps) => { height="100vh" $backgroundColor="white" > - + - + {isLogined ? ( + + ) : ( + + )} { name: 'Patrick', email: 'qkrtk9230@naver.com', }); + const user = JSON.parse(localStorage.getItem('user') || ''); // useEffect(()=>{ // setMyInfoName() @@ -44,11 +45,7 @@ const MyInfo = () => { $justifyContent="center" $alignItems="center" > - {isThereImg ? ( - - ) : ( - - )} + @@ -58,14 +55,12 @@ const MyInfo = () => { {myInfoNameAndEmail.email} - - - ); }; const MyInfoContainer = styled(Flex)` + position: relative; border: 1px solid ${({ theme }) => theme.color.lightGray}; `; @@ -76,10 +71,4 @@ const MyInfoImg = styled.img` border-radius: 50%; `; -const MyInfoModifyIcon = styled(Box)` - position: absolute; - right: 32px; - top: 32px; -`; - export default MyInfo; diff --git a/frontend/src/components/MyInfoContainer/MyInfoList/index.tsx b/frontend/src/components/MyInfoContainer/MyInfoList/index.tsx new file mode 100644 index 000000000..f69c2d1b6 --- /dev/null +++ b/frontend/src/components/MyInfoContainer/MyInfoList/index.tsx @@ -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([]); + + const getMyInfoListFromServer = async () => { + const serverMyInfoTopics = await getApi( + 'default', + '/members/my/topics', + ); + setMyInfoTopics(serverMyInfoTopics); + }; + + useEffect(() => { + getMyInfoListFromServer(); + }, []); + + if (!myInfoTopics) return <>; + + return ( + + {myInfoTopics.map((topic, index) => { + return ( + + + + ); + })} + + ); +}; + +const MyInfoListWrapper = styled.ul` + display: grid; + grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); + grid-row-gap: ${({ theme }) => theme.spacing[5]}; +`; + +export default MyInfoList; diff --git a/frontend/src/components/MyInfoContainer/index.tsx b/frontend/src/components/MyInfoContainer/index.tsx new file mode 100644 index 000000000..a7b858921 --- /dev/null +++ b/frontend/src/components/MyInfoContainer/index.tsx @@ -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) => ( +
+ + + + {containerTitle} + + + + {containerDescription} + + + + + + + }> + + +
+); + +const SeeAllButton = styled(Button)` + cursor: pointer; +`; + +export default MyInfoContainer; diff --git a/frontend/src/components/NotFound/LoginError.tsx b/frontend/src/components/NotFound/LoginError.tsx index e410b7d0f..b8b62d3fc 100644 --- a/frontend/src/components/NotFound/LoginError.tsx +++ b/frontend/src/components/NotFound/LoginError.tsx @@ -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 ( { 나만의 지도를 만들어 보세요. - 카카오로 시작하기 + + 카카오로 시작하기 +
); diff --git a/frontend/src/components/PinCard/index.tsx b/frontend/src/components/PinCard/index.tsx new file mode 100644 index 000000000..c1d6c9519 --- /dev/null +++ b/frontend/src/components/PinCard/index.tsx @@ -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 = ({ + pinId, + pinTitle, + pinAddress, + pinDescription, +}: PinCardProps) => { + const { routePage } = useNavigator(); + + return ( + + + + + + {pinTitle} + + + + + + + {pinAddress} + + + + + {pinDescription} + + + + + ); +}; + +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; diff --git a/frontend/src/pages/Profile.tsx b/frontend/src/pages/Profile.tsx index cf3fe6976..e8f2a5c86 100644 --- a/frontend/src/pages/Profile.tsx +++ b/frontend/src/pages/Profile.tsx @@ -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
profile
; + const goToPopularTopics = () => { + routePage('/see-all/popularity'); + }; + + return ( + + + + + + + + ); }; +const ProfileWrapper = styled(Box)` + width: 70vw; + margin: 0 auto; +`; + +const MyInfoWrapper = styled(Flex)` + margin-top: ${({ theme }) => theme.spacing[6]}; +`; export default Profile; diff --git a/frontend/src/router.tsx b/frontend/src/router.tsx index f7c6bfa6e..f23c1e8f6 100644 --- a/frontend/src/router.tsx +++ b/frontend/src/router.tsx @@ -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 { @@ -92,7 +93,7 @@ const routes: routeElement[] = [ }, { path: '/askLogin', - element: , + element: , withAuth: false, }, ], diff --git a/frontend/src/types/MyInfo.ts b/frontend/src/types/MyInfo.ts index 352df24de..8e3b86198 100644 --- a/frontend/src/types/MyInfo.ts +++ b/frontend/src/types/MyInfo.ts @@ -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; +}