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

리뷰 방법 안내 페이지 구현 (issue#52) #56

Merged
merged 4 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frontend/src/apis/authAPI.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UserInfo } from '@/types';
import type { UserInfo } from '@/types';

//TODO 일단 관심사 별로 API.ts 로 나누어 놓은 것인데,
// 이 또한 추후에 논의해보아야 할듯 해요 ~ @버건디
Expand Down
142 changes: 142 additions & 0 deletions frontend/src/components/guide/HowToFork.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// TODO 안에 컨텐츠가 어떻게 들어갈지 몰라서 일단 목파일 넣어놓습니다. @버건디

const HowToFork = () => {
return (
<div id="Inner">
<div id="Languages">
<a href="http://hy.lipsum.com/">Հայերեն</a>
<a href="http://sq.lipsum.com/">Shqip</a>
<span className="ltr" dir="ltr">
<a href="http://ar.lipsum.com/">‫العربية</a>
</span>
<a href="http://bg.lipsum.com/">Български</a>
<a href="http://ca.lipsum.com/">Català</a>
<a href="http://cn.lipsum.com/">中文简体</a>
<a href="http://hr.lipsum.com/">Hrvatski</a>
<a href="http://cs.lipsum.com/">Česky</a>
<a href="http://da.lipsum.com/">Dansk</a>
<a href="http://nl.lipsum.com/">Nederlands</a>
<a className="zz" href="http://www.lipsum.com/">
English
</a>
<a href="http://et.lipsum.com/">Eesti</a>
<a href="http://ph.lipsum.com/">Filipino</a>
<a href="http://fi.lipsum.com/">Suomi</a>
<a href="http://fr.lipsum.com/">Français</a>
<a href="http://ka.lipsum.com/">ქართული</a>
<a href="http://de.lipsum.com/">Deutsch</a>
<a href="http://el.lipsum.com/">Ελληνικά</a>
<span className="ltr" dir="ltr">
<a href="http://he.lipsum.com/">‫עברית</a>
</span>
<a href="http://hi.lipsum.com/">हिन्दी</a>
<a href="http://hu.lipsum.com/">Magyar</a>
<a href="http://id.lipsum.com/">Indonesia</a>
<a href="http://it.lipsum.com/">Italiano</a>
<a href="http://lv.lipsum.com/">Latviski</a>
<a href="http://lt.lipsum.com/">Lietuviškai</a>
<a href="http://mk.lipsum.com/">македонски</a>
<a href="http://ms.lipsum.com/">Melayu</a>
<a href="http://no.lipsum.com/">Norsk</a>
<a href="http://pl.lipsum.com/">Polski</a>
<a href="http://pt.lipsum.com/">Português</a>
<a href="http://ro.lipsum.com/">Româna</a>
<a href="http://ru.lipsum.com/">Pyccкий</a>
<a href="http://sr.lipsum.com/">Српски</a>
<a href="http://sk.lipsum.com/">Slovenčina</a>
<a href="http://sl.lipsum.com/">Slovenščina</a>
<a href="http://es.lipsum.com/">Español</a>
<a href="http://sv.lipsum.com/">Svenska</a>
<a href="http://th.lipsum.com/">ไทย</a>
<a href="http://tr.lipsum.com/">Türkçe</a>
<a href="http://uk.lipsum.com/">Українська</a>
<a href="http://vi.lipsum.com/">Tiếng Việt</a>
</div>

<h1>Lorem Ipsum</h1>
<h4>
"Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci
velit..."
</h4>
<h5>
"There is no one who loves pain itself, who seeks after it and wants to have it, simply
because it is pain..."
</h5>

<hr />

<div id="Content">
<div className="boxed">
<div id="lipsum">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut convallis enim elementum
nulla posuere eleifend. Vestibulum sit amet venenatis libero. Suspendisse porttitor
sit amet ligula et placerat. Pellentesque habitant morbi tristique senectus et netus
et malesuada fames ac turpis egestas. Cras dignissim non urna in fermentum. Vivamus
egestas odio et rutrum ultricies. Aliquam gravida, lectus non tristique commodo,
ligula eros ultrices turpis, quis malesuada quam lectus nec metus. Pellentesque
habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
</p>
<p>
Nullam viverra eu augue id aliquet. Nulla sit amet lobortis ipsum. Suspendisse
suscipit viverra ante vitae semper. Aliquam enim felis, iaculis a posuere pharetra,
lacinia eu tortor. Aliquam posuere suscipit cursus. Vivamus semper volutpat urna, eu
dignissim lectus ullamcorper eget. Duis placerat molestie sapien, nec commodo felis
vulputate at.
</p>
<p>
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
himenaeos. In vehicula, est id efficitur porta, orci velit ultrices enim, a dignissim
augue ligula at felis. Phasellus elementum nibh felis, ac viverra nunc elementum at.
Phasellus eu pellentesque libero. In convallis erat diam, vitae hendrerit ante posuere
a. In hac habitasse platea dictumst. Pellentesque at lectus eu nulla ullamcorper
ornare ut et urna.
</p>
<p>
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia
curae; Nullam vulputate et nisi et iaculis. Donec iaculis ut nibh venenatis efficitur.
Nunc lorem justo, sagittis vitae lacus eu, tincidunt placerat justo. Aenean semper
nibh at sodales convallis. Duis ut iaculis arcu. Proin commodo rutrum nisl eget
venenatis. Quisque sodales magna sit amet turpis tristique faucibus. Aenean a porta
ex, at feugiat risus. Nulla tincidunt consectetur pellentesque. Integer semper, diam
quis porttitor porttitor, elit nunc ullamcorper dui, quis consectetur metus enim ac
nunc. Nulla egestas justo at auctor fringilla.
</p>
<p>
Mauris pharetra ut eros quis euismod. Sed efficitur erat id dui mollis venenatis. Duis
blandit, nisl vel venenatis fermentum, justo purus consectetur nibh, quis rutrum mi
eros id est. Sed mattis commodo leo. Donec lacinia mi sed laoreet imperdiet. Mauris ac
ex congue, consequat arcu eu, egestas metus. Duis imperdiet diam quis tellus pretium
ultricies. Quisque sagittis sit amet nisi id vulputate. Interdum et malesuada fames ac
ante ipsum primis in faucibus. Maecenas sagittis enim id porta fringilla. Nunc vel
faucibus massa. Nam rhoncus ex quis augue viverra, non aliquet mauris imperdiet. Donec
tincidunt enim sed justo posuere tempus. Suspendisse justo velit, vehicula id tellus
eu, condimentum posuere nibh.
</p>
</div>
<div id="generated">
Generated 5 paragraphs, 397 words, 2706 bytes of{' '}
<a href="https://www.lipsum.com/" title="Lorem Ipsum">
Lorem Ipsum
</a>
</div>
</div>
</div>

<hr />

<div className="boxed">
<a style={{ textDecoration: 'none' }} href="mailto:help@lipsum.com">
help@lipsum.com
</a>
<br />
<a style={{ textDecoration: 'none' }} rel="nofollow" href="/privacy">
Privacy Policy
</a>
·<button id="pmLink">Privacy Manager</button>
</div>
</div>
);
};

export default HowToFork;
64 changes: 64 additions & 0 deletions frontend/src/components/tab/Tab.styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { keyframes, styled } from 'styled-components';

export const TabPageContainer = styled.div`
width: 70rem;
height: 100%;
margin: 0 auto;
padding-top: 3rem;
`;

export const TabListContainer = styled.div`
display: flex;
justify-content: center;
`;

const fadeIn = keyframes`
from {
opacity: 0;
}
to {
opacity: 1;
}
`;

export const TabCurrentContentContainer = styled.div`
word-break: break-all;
margin-top: 2rem;
animation: ${fadeIn} 0.3s ease-out;
Copy link
Contributor

Choose a reason for hiding this comment

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

오 애니메이션까지 넣어주셨군요 👍👍

`;

export const TabContainer = styled.div<{ selected: boolean }>`
Copy link
Contributor

@Parkhanyoung Parkhanyoung Jul 18, 2024

Choose a reason for hiding this comment

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

Suggested change
export const TabContainer = styled.div<{ selected: boolean }>`
export const TabContainer = styled.div<{ isSelected: boolean }>`

앞에 is 붙여주면 좋을 것 같습니다 🫡

Copy link
Contributor Author

Choose a reason for hiding this comment

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

수정하였어요! 짚어주셔서 감사합니다 🙇

padding: 10px 20px;
cursor: pointer;
background: ${({ selected }) => (selected ? 'var(--primary-700)' : 'var(--grey-700)')};
font-size: 1.5rem;
color: white;
border-radius: 1rem 1rem 0 0;
margin: 0 5px;
transition:
background 0.3s,
box-shadow 0.3s;

${({ selected }) =>
selected &&
`
box-shadow: 0 0.4rem 0.8rem rgba(0, 0, 0, 0.2);
animation: tabSelected 0.3s ease-out;
`}

&:hover {
background: ${({ selected }) => (selected ? 'var(--primary-500)' : 'var(--grey-500)')};
}

@keyframes tabSelected {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
`;
16 changes: 16 additions & 0 deletions frontend/src/components/tab/Tab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useTabs } from '@/hooks/useTabs';
import { PropsWithChildren } from 'react';
import * as S from './Tab.styled';

interface TabProps extends PropsWithChildren {
index: number;
}

export default function Tab({ index, children }: TabProps) {
const { selectedIndex, handleSelectedIndex } = useTabs();
return (
<S.TabContainer selected={selectedIndex === index} onClick={() => handleSelectedIndex(index)}>
{children}
</S.TabContainer>
);
}
10 changes: 10 additions & 0 deletions frontend/src/components/tab/TabCurrentTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { useTabs } from '@/hooks/useTabs';
import * as S from './Tab.styled';

export default function TabCurrentTab() {
const { selectedIndex, tabList } = useTabs();

return (
<S.TabCurrentContentContainer>{tabList[selectedIndex].content}</S.TabCurrentContentContainer>
Copy link
Contributor

Choose a reason for hiding this comment

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

사소하지만, 여기 컴포넌트 명에 따라서 CurrentTabContainer로 바꿔도 좋을 것 같아요~!

Suggested change
<S.TabCurrentContentContainer>{tabList[selectedIndex].content}</S.TabCurrentContentContainer>
<S.CurrentTabContainer>{tabList[selectedIndex].content}</S.CurrentTabContainer>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

짚어주셔서 감사합니다 :)

);
}
6 changes: 6 additions & 0 deletions frontend/src/components/tab/TabList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { PropsWithChildren } from 'react';
import * as S from './Tab.styled';

export default function TabList({ children }: PropsWithChildren) {
return <S.TabListContainer>{children}</S.TabListContainer>;
}
29 changes: 29 additions & 0 deletions frontend/src/components/tab/Tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { TabsContext } from '@/hooks/useTabs';
import { PropsWithChildren, useState } from 'react';
import Tab from './Tab';
import TabList from './TabList';
import TabCurrentTab from './TabCurrentTab';
import * as S from './Tab.styled';
import { TabData } from '@/types';

interface TabsProps extends PropsWithChildren {
tabList: TabData[];
}

export default function Tabs({ children, tabList }: TabsProps) {
Copy link
Contributor

@Parkhanyoung Parkhanyoung Jul 18, 2024

Choose a reason for hiding this comment

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

TabList와 Tabs가 네이밍만 봤을 때는 헷갈릴 수도 있겠다는 생각이 들었습니다. 그런데 어떻게 개선해볼 수 있을지는 잘 안 떠오르네요 🥲🥲 혹시 버건디에게 좋은 아이디어가 있으실까요?

Copy link
Contributor

Choose a reason for hiding this comment

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

TabList는 TabMenu 어떨까요? 혹은 TabHeader도 제안드려요! (더 좋은 네이밍 있으면 적극 환영입니다🙌)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

두분 다 감사드려용~~ 한번 수정해보았는데, 추가적으로 수정할 부분 있으면 말씀 주세요!!

const [selectedIndex, setSelectedIndex] = useState(0);

const handleSelectedIndex = (index: number) => {
setSelectedIndex(index);
};

return (
<TabsContext.Provider value={{ selectedIndex, handleSelectedIndex, tabList }}>
<S.TabPageContainer>{children}</S.TabPageContainer>
</TabsContext.Provider>
);
}

Tabs.List = TabList;
Tabs.Tab = Tab;
Tabs.CurrentTab = TabCurrentTab;
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ChangeEvent, useState } from 'react';
import { UserInfo } from '@/types';
import { useState } from 'react';
import type { ChangeEvent } from 'react';
import type { UserInfo } from '@/types';
import * as S from './UserProfile.styled';

type UserProfileDescription = Pick<UserInfo, 'description'>;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/userProfile/UserProfileEmail.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UserInfo } from '@/types';
import type { UserInfo } from '@/types';
import * as S from './UserProfile.styled';

type UserProfileEmailProps = Pick<UserInfo, 'email'>;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/userProfile/UserProfileImage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as S from './UserProfile.styled';
import { UserInfo } from '@/types';
import type { UserInfo } from '@/types';

//TODO UserInfo 타입에서 재사용할 수 있을것 같아 Pick으로 선언해놓습니다.
// 인터페이스로 추후에 변경 해도 상관 없어요! @버건디
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/userProfile/UserProfileName.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UserInfo } from '@/types';
import type { UserInfo } from '@/types';
import * as S from './UserProfile.styled';

type UserProfileNameProps = Pick<UserInfo, 'name'>;
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/constants/messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const ERROR_MESSAGE = {
not_defined_context: '컨텍스트가 정의 되지 않았어요!',
} as const;
1 change: 1 addition & 0 deletions frontend/src/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export const ROUTES = {
submit: '/submit/:id',
missionDetail: '/missions/:id',
profile: '/profile',
guide: '/guide',
} as const;
21 changes: 21 additions & 0 deletions frontend/src/hooks/useTabs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { createContext, useContext } from 'react';
import { ERROR_MESSAGE } from '@/constants/messages';
import { TabData } from '@/types';

interface TabsContextProps {
selectedIndex: number;
handleSelectedIndex: (index: number) => void;
tabList: TabData[];
}

// TODO 컨텍스트 폴더를 따로 뺄지 안뺄지 이야기 나눠보아야 할거 같아요 ! @버건디
Copy link
Contributor

Choose a reason for hiding this comment

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

저는 컨텍스트 폴더 분리하는 것 좋습니다!


export const TabsContext = createContext<TabsContextProps | undefined>(undefined);

export const useTabs = (): TabsContextProps => {
const context = useContext(TabsContext);
if (!context) {
throw new Error(ERROR_MESSAGE.not_defined_context);
}
return context;
};
2 changes: 1 addition & 1 deletion frontend/src/hooks/useUserInfo.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useQuery } from '@tanstack/react-query';
import { getUserInfo } from '@/apis/authAPI';
import { UserInfo } from '@/types';
import type { UserInfo } from '@/types';

const useUserInfo = () => {
//TODO 아직 토큰 로직에 관한 부분이 미정이라서
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import MissionDetailPage from './pages/MissionDetailPage';
import MissionListPage from './pages/MissionListPage';
import MissionSubmitPage from './pages/MissionSubmitPage';
import UserProfilePage from './pages/UserProfilePage';
import GuidePage from './pages/GuidePage';

const queryClient = new QueryClient();

Expand Down Expand Up @@ -48,6 +49,14 @@ const routes = [
</App>
),
},
{
path: ROUTES.guide,
element: (
<App>
<GuidePage />
</App>
),
},
];

const router = createBrowserRouter(routes, {
Expand Down
Loading