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.
24 changes: 22 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,11 @@ const Layout = ({ children }: LayoutProps) => {
const { Tmapv3 } = window;
const mapContainer = useRef(null);
const { width } = useContext(LayoutWidthContext);
const isLogined = localStorage.getItem('userToken');

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

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

Expand Down Expand Up @@ -58,9 +64,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="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 onClick={loginButtonClick} />
)}
</Flex>
<Flex
height="calc(100vh - 40px)"
Expand Down Expand Up @@ -88,4 +101,11 @@ const LayoutFlex = styled(Flex)`
transition: all ease 0.3s;
`;

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

border-radius: 50%;
`;

export default Layout;
7 changes: 2 additions & 5 deletions frontend/src/components/MyInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,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="https://images.unsplash.com/photo-1480429370139-e0132c086e2a?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=988&q=80" />
<Space size={7} />
<Box>
<Text color="black" $fontSize="default" $fontWeight="normal">
Expand All @@ -66,6 +62,7 @@ const MyInfo = () => {
};

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

Expand Down
161 changes: 161 additions & 0 deletions frontend/src/components/MyInfoContainer/MyInfoList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
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 data = [
{
id: 1,
name: '준팍의 또 토픽',
image: 'https://map-befine-official.github.io/favicon.png',
pinCount: 3,
bookmarkCount: 0,
isBookmarked: false,
updatedAt: '2023-08-14T13:15:40.15966098',
},
{
id: 2,
name: '준팍의 두번째 토픽',
image: 'https://map-befine-official.github.io/favicon.png',
pinCount: 5,
bookmarkCount: 0,
isBookmarked: false,
updatedAt: '2023-08-14T13:15:40.15966888',
},
{
id: 3,
name: '준팍의 또 토픽',
image: 'https://map-befine-official.github.io/favicon.png',
pinCount: 3,
bookmarkCount: 0,
isBookmarked: false,
updatedAt: '2023-08-14T13:15:40.15966098',
},
{
id: 4,
name: '준팍의 두번째 토픽',
image: 'https://map-befine-official.github.io/favicon.png',
pinCount: 5,
bookmarkCount: 0,
isBookmarked: false,
updatedAt: '2023-08-14T13:15:40.15966888',
},
];

const data2 = [
{
id: 1,
name: '매튜의 산스장',
address: '지번 주소',
description: '매튜가 사랑하는 산스장',
latitude: 37.0,
longitude: 127.0,
},
{
id: 2,
name: '매튜의 안갈집',
address: '지번 주소',
description: '매튜가 두번은 안 갈 집',
latitude: 37.0,
longitude: 127.0,
},
{
id: 3,
name: '매튜의 산스장',
address: '지번 주소',
description: '매튜가 사랑하는 산스장',
latitude: 37.0,
longitude: 127.0,
},
{
id: 4,
name: '매튜의 안갈집',
address: '지번 주소',
description: '매튜가 두번은 안 갈 집',
latitude: 37.0,
longitude: 127.0,
},
];

interface MyInfoListProps {
isTopic: boolean;
}

const MyInfoList = ({ isTopic }: MyInfoListProps) => {
const [myInfoTopics, setMyInfoTopics] = useState<MyInfoTopicType[]>([]);
const [myInfoPins, setMyInfoPins] = useState<MyInfoPinType[]>([]);
Copy link
Collaborator

Choose a reason for hiding this comment

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

재사용의 관점에서는 지금도 충분히 좋습니다만, MyInfoList 컴포넌트는 껍데기 UI만 유지하고 props 받은 값들을 렌더링할 수 있도록 하는 것도 괜찮아보여요.

Fetching 로직도 분기처리하고 있기 때문에 위 상태들을 부모로 올리고 fetching 로직을 분리해서 실행시킨 후 set 된 값들을 props로 이 컴포넌트에 전달하는 것이 어떨까 하는 생각도 드네요.

아니면 아예 topic, pin 이렇게 나누는 것도 고려해볼만 하네욥~~ 물론 제 얇은 지식이기에 내일 다시 보면 생각 바뀌어서 이 코멘트를 삭제할 수도 있을거 같아요 🤪

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

<세인과 페어 프로그래밍 완료. 나중에 리팩토링 하기로 결정!>


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

if (!isTopic) {
const serverMyInfoPins = await getApi<MyInfoPinType[]>(
'default',
'/members/topics',
);
setMyInfoPins(serverMyInfoPins);
}
};

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

if (!isTopic)
return (
<MyInfoListWrapper>
{data2.map((pin, index) => {
return (
index < 3 && (
<Fragment key={pin.id}>
<PinCard
pinId={pin.id}
pinTitle={pin.name}
pinAddress={pin.address}
pinDescription={pin.description}
/>
</Fragment>
)
);
})}
</MyInfoListWrapper>
);

if (!data) return <></>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

이 early return 이 !isTopic 보다 위에 있으면 좋을 것 같아요~~

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

와우 제가 캐치 하지 못한 부분을 잡아주시다니 바로 반영하겠습니닷 !!!


return (
<MyInfoListWrapper>
{data.map((topic, index) => {
return (
index < 3 && (
<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;
67 changes: 67 additions & 0 deletions frontend/src/components/MyInfoContainer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
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;
routeWhenSeeAll: () => void;
}

const MyInfoContainer = ({
containerTitle,
containerDescription,
routeWhenSeeAll,
}: 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>

{
<SeeAllButton variant="primary" onClick={routeWhenSeeAll}>
전체 보기
</SeeAllButton>
}
</Flex>

<Space size={4} />

<Suspense fallback={<TopicCardListSeleton />}>
{containerTitle === '나의 핀' ? (
<MyInfoList isTopic={false} />
) : (
<MyInfoList isTopic={true} />
)}
</Suspense>
</section>
);

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

export default MyInfoContainer;
10 changes: 8 additions & 2 deletions frontend/src/components/NotFound/LoginError.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ 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"
$justifyContent="center"
$alignItems="center"
width="100vw"
width="100%"
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.

이 부분 사이드바가 축소 되었을 때 지도를 보이게 하려고 했었는데 지금 생각해보니 모아보기와 즐겨찾기, 프로필 기능 쓸 때 모두 전체 화면이라 100vw로 두는게 좋을 것 같습니다!

height="100vh"
>
<LoginErrorIcon />
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
Loading