-
Notifications
You must be signed in to change notification settings - Fork 78
[이승헌] sprint10 #660
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
Open
heony704
wants to merge
42
commits into
codeit-bootcamp-frontend:Next.js-이승헌
Choose a base branch
from
heony704:Next.js-이승헌-sprint10
base: Next.js-이승헌
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
The head ref may contain hidden characters: "Next.js-\uC774\uC2B9\uD5CC-sprint10"
Open
[이승헌] sprint10 #660
Changes from all commits
Commits
Show all changes
42 commits
Select commit
Hold shift + click to select a range
1bf8fdd
remove: 초기 세팅 파일 중 필요없는 파일, 코드 제거
c6c8f11
chore: prettier 설치 및 설정
cfb3206
chore: tailwindcss 설치 및 설정
f7efed7
chore: import & tailwindcss 순서 정렬, import alias 설정
d043dd6
style: 기본 색상 추가
449a096
feat: 버튼 컴포넌트 구현
ae39b95
feat: 헤더 컴포넌트 구현
7ad8833
feat: 헤더를 모든 페이지에 적용
aa77fc8
style: 헤더 아래 여백 추가
d3c64b6
remove: 사용되지 않는 pages폴더의 api 삭제
32afc20
chore: axios 설치 및 초기 세팅
8d20bb1
feat: 자유게시판 특정 글 받아오는 api 구현
39e97dc
feat: html 메타 태그 전체 페이지에 적용
129ed7a
feat: 헤더 네비게이션 메뉴 표시 수정
fa69022
fix: html에 실수로 들어간 세미콜론 제거
6fd62ba
style: pre 태그 속 내용물 넘치지 않게 스타일 적용
1e1a8ec
chore: 외부 이미지를 사용하기 위한 next config 설정
31cf35d
feat: 게시판 댓글 관련 api 추가
20507c6
feat: 게시글 상세 페이지 구현
9b76206
refactor: Button Prop을 좀 더 상세한 타입으로 수정
d4a9a5d
feat: favicon 수정
13621d4
feat: 로그인, 회원가입 페이지는 헤더 표시 안함
4423751
feat: Pretendard 폰트 적용
73f32c9
style: 댓글 여백 수정
1e4cdb5
refactor: 반응형 브레이크포인트 변수로 관리
162d168
feat: 레이아웃 수정
f8b00b6
feat: 홈페이지에 footer 추가
e717ca2
refactor: 이미지 파일들은 public/images 폴더로 이동
207bf37
refactor: 로고만 있는 헤더를 컴포넌트로 분리
ee67b01
feat: 메인 페이지 구현
4f3ea82
style: 데스크탑 브레이크포인트 1280px로 변경
d92c5e5
style: 헤더 네비게이바 글자 수직 가운데 정렬
3780dab
feat: 게시글 댓글 없을 때 대체 UI 표시
heony704 ea5addb
style: 입력창 focus outline 스타일 수정
heony704 311b754
refactor: type들 따로 파일로 분리해서 관리
heony704 ef33223
refactor: import path 룰 수정
heony704 657456a
refactor: Comment 타입, Writer 타입 분리
heony704 27f2aac
refactor: 댓글 구분선을 댓글이 아닌 댓글 외부에서 스타일하도록 수정
heony704 6afda06
refactor: 댓글폼, 댓글, 목록으로 돌아가기 버튼을 컴포넌트로 분리
heony704 47a9bbe
style: 게시글과 댓글 사이에 가로선 추가
heony704 48763da
feat: 제품 상세 페이지 구현
heony704 ba2abd9
fix: 이미지 오류 수정
heony704 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
{ | ||
"extends": "next/core-web-vitals" | ||
"extends": ["next/core-web-vitals", "prettier"] | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"arrowParens": "always", | ||
"endOfLine": "lf", | ||
"printWidth": 80, | ||
"quoteProps": "as-needed", | ||
"semi": true, | ||
"singleQuote": true, | ||
"tabWidth": 2, | ||
"useTabs": false, | ||
"trailingComma": "es5", | ||
|
||
"importOrder": [ | ||
"<THIRD_PARTY_MODULES>", | ||
|
||
"^@/apis/(.*)$", | ||
"^@/hooks/(.*)$", | ||
"^@/components/(.*)$", | ||
"^@/utils/(.*)$", | ||
"^@/types/(.*)$", | ||
|
||
"^[./]" | ||
], | ||
"importOrderSeparation": true, | ||
"importOrderSortSpecifiers": true, | ||
|
||
"plugins": [ | ||
"@trivago/prettier-plugin-sort-imports", | ||
"prettier-plugin-tailwindcss" | ||
] | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import axios from './instance'; | ||
|
||
export async function getBoardById(id: number) { | ||
const res = await axios.get(`/articles/${id}`); | ||
return res.data; | ||
} | ||
|
||
export async function getBoardComments(boardId: number) { | ||
const res = await axios.get(`/articles/${boardId}/comments?limit=100`); | ||
return res.data.list; | ||
} | ||
|
||
export async function postBoardComment(boardId: number, content: string) { | ||
const res = await axios.post(`/articles/${boardId}/comments`, { content }); | ||
return res.data; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import axios from 'axios'; | ||
|
||
const instance = axios.create({ | ||
baseURL: 'https://panda-market-api.vercel.app', | ||
}); | ||
|
||
export default instance; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import axios from './instance'; | ||
|
||
export async function getProductById(id: number) { | ||
const res = await axios.get(`/products/${id}`); | ||
return res.data; | ||
} | ||
|
||
export async function getProductComments(productId: number) { | ||
const res = await axios.get(`/products/${productId}/comments?limit=100`); | ||
return res.data.list; | ||
} | ||
|
||
export async function postProductComment(productId: number, content: string) { | ||
const res = await axios.post(`/products/${productId}/comments`, { content }); | ||
return res.data; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { Url } from 'next/dist/shared/lib/router/router'; | ||
import Image from 'next/image'; | ||
import { useRouter } from 'next/router'; | ||
|
||
import Button from './Button'; | ||
|
||
type BackButtonProp = { | ||
to: Url; | ||
}; | ||
|
||
export default function BackButton({ to }: BackButtonProp) { | ||
const { push } = useRouter(); | ||
|
||
const handleButtonClick = () => { | ||
push(to); | ||
}; | ||
|
||
return ( | ||
<Button | ||
style={{ shape: 'rounded', size: 'large' }} | ||
onClick={handleButtonClick} | ||
> | ||
목록으로 돌아가기 | ||
<Image | ||
src="/images/ic_back.svg" | ||
width={24} | ||
height={24} | ||
className="ml-[10px]" | ||
alt="뒤로가기 아이콘" | ||
/> | ||
</Button> | ||
); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { MouseEventHandler, ReactNode } from 'react'; | ||
|
||
type Props = { | ||
style?: { | ||
shape?: 'square' | 'rounded'; | ||
size?: 'small' | 'large'; | ||
}; | ||
disabled?: boolean; | ||
onClick: MouseEventHandler<HTMLButtonElement>; | ||
children: ReactNode; | ||
}; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
이유는 해당 tag의 native 이벤트(클릭, 포커스, 블러 등)를 컴포넌트 외부에서도 조정할 수 있게 끔 하기 위해서입니다. interface ButtonProps extends PropsWithChildren {};
const Button = forwardRef<HTMLButtonElement, ButtonProps>( (props, ref) => {
const {children} = props;
return (
<button ref={ref}>{children}</button>
)
})
// ./page or ./component
const DummyComponent= () => {
const buttonRef = useRef<HTMLButtonElement>(null);
const hanldeClickTrigger = () => {
buttonRef.current?.click();
}
return (
<>
<Button ref={buttonRef} onClick={() => console.log("cliced by trigger-button")} />
<button onClick={hanldeClickTrigger}>trigger-button</button>
<>
)
} |
||
export default function Button({ | ||
style = { shape: 'square', size: 'small' }, | ||
disabled = false, | ||
onClick, | ||
children, | ||
}: Props) { | ||
return ( | ||
<button | ||
className={`${style.size === 'small' ? 'h-[42px] px-6' : 'h-12 px-9'} ${style.shape === 'square' ? 'rounded-lg' : 'rounded-full'} flex cursor-pointer items-center justify-center bg-primary-400 text-base font-semibold text-white hover:bg-primary-600 active:bg-primary-700 disabled:cursor-default disabled:bg-gray-400`} | ||
disabled={disabled} | ||
onClick={onClick} | ||
> | ||
{children} | ||
</button> | ||
); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import Image from 'next/image'; | ||
|
||
import { formatDateToTimeAgo } from '@/utils/formatDateToString'; | ||
|
||
import { BoardComment } from '@/types/board'; | ||
|
||
type CommentProp = { | ||
comment: BoardComment; | ||
}; | ||
|
||
export default function Comment({ comment }: CommentProp) { | ||
const { content, createdAt, writer } = comment; | ||
|
||
return ( | ||
<div className="relative my-4 flex flex-col tablet:my-6"> | ||
<Image | ||
src="/images/ic_kebab.svg" | ||
width={24} | ||
height={24} | ||
className="absolute right-0 top-0" | ||
alt="댓글 메뉴 아이콘" | ||
/> | ||
<p className="text-sm font-normal text-gray-800">{content}</p> | ||
<div className="mt-4 flex items-center tablet:mt-6"> | ||
<Image | ||
src={writer.image ?? '/images/img_default_profile.svg'} | ||
width={32} | ||
height={32} | ||
className="max-h-8 rounded-full" | ||
alt="댓글쓴이 프로필 이미지" | ||
/> | ||
<div className="ml-2 flex flex-col"> | ||
<p className="text-xs font-normal text-gray-600">{writer.nickname}</p> | ||
<p className="text-xs font-normal text-gray-400"> | ||
{formatDateToTimeAgo(new Date(createdAt))} | ||
</p> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { ChangeEvent, useState } from 'react'; | ||
|
||
import Button from '@/components/Button'; | ||
|
||
type CommentFormProp = { | ||
placeholder?: string; | ||
onSubmit: (inputValue: string) => void; | ||
}; | ||
|
||
export default function CommentForm({ | ||
placeholder = '', | ||
onSubmit, | ||
}: CommentFormProp) { | ||
const [value, setValue] = useState<string>(''); | ||
|
||
const handleTextareaChange = (e: ChangeEvent<HTMLTextAreaElement>) => { | ||
setValue(e.target.value); | ||
}; | ||
|
||
const handleSubmitButtonClick = () => { | ||
onSubmit(value); | ||
setValue(''); | ||
}; | ||
|
||
return ( | ||
<> | ||
<textarea | ||
className="h-[104px] resize-none rounded-xl bg-gray-100 px-6 py-4 text-base font-normal text-gray-800 placeholder:text-gray-400" | ||
placeholder={placeholder} | ||
value={value} | ||
onChange={handleTextareaChange} | ||
/> | ||
<div className="flex justify-end"> | ||
<Button | ||
style={{ shape: 'square', size: 'small' }} | ||
disabled={value === ''} | ||
onClick={handleSubmitButtonClick} | ||
> | ||
등록 | ||
</Button> | ||
</div> | ||
</> | ||
); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import Image from 'next/image'; | ||
import Link from 'next/link'; | ||
|
||
type Nav = { | ||
name: string; | ||
url: string; | ||
}; | ||
|
||
type Social = { | ||
name: string; | ||
url: string; | ||
iconSrc: string; | ||
}; | ||
|
||
const NAVS: Nav[] = [ | ||
{ | ||
name: 'Privacy Policy', | ||
url: '/privacy', | ||
}, | ||
{ | ||
name: 'FAQ', | ||
url: '/faq', | ||
}, | ||
]; | ||
|
||
const SOCIALS: Social[] = [ | ||
{ | ||
name: '페이스북', | ||
url: 'https://www.facebook.com/', | ||
iconSrc: '/images/ic_facebook.svg', | ||
}, | ||
{ | ||
name: '트위터', | ||
url: 'https://twitter.com/?lang=ko', | ||
iconSrc: '/images/ic_twitter.svg', | ||
}, | ||
{ | ||
name: '유튜브', | ||
url: 'https://www.youtube.com/', | ||
iconSrc: '/images/ic_youtube.svg', | ||
}, | ||
{ | ||
name: '인스타그램', | ||
url: 'https://www.instagram.com/', | ||
iconSrc: '/images/ic_instagram.svg', | ||
}, | ||
]; | ||
|
||
export default function Footer() { | ||
return ( | ||
<footer className="h-40 bg-gray-900"> | ||
<div className="m-auto flex h-full max-w-[1920px] flex-wrap-reverse items-end justify-between p-8 text-base font-normal tablet:px-[104px] desktop:px-[200px]"> | ||
<div className="grow basis-full self-start text-gray-400 tablet:grow-0 tablet:basis-auto tablet:self-auto"> | ||
©codeit - 2024 | ||
</div> | ||
<div className="flex gap-[30px]"> | ||
{NAVS.map((nav) => ( | ||
<Link | ||
href={nav.url} | ||
className="text-gray-200 active:text-primary-400" | ||
key={nav.name} | ||
> | ||
{nav.name} | ||
</Link> | ||
))} | ||
</div> | ||
<div className="flex gap-3"> | ||
{SOCIALS.map((social) => ( | ||
<Link | ||
href={social.url} | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
key={social.name} | ||
> | ||
<Image | ||
width={20} | ||
height={20} | ||
src={social.iconSrc} | ||
alt={`${social.name} 아이콘`} | ||
/> | ||
</Link> | ||
))} | ||
</div> | ||
</div> | ||
</footer> | ||
); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { useRouter } from 'next/router'; | ||
|
||
import Footer from './Footer'; | ||
import LogoHeader from './LogoHeader'; | ||
import MainHeader from './MainHeader'; | ||
|
||
type Props = { | ||
children: React.ReactNode; | ||
}; | ||
|
||
export default function Layout({ children }: Props) { | ||
const { asPath } = useRouter(); | ||
|
||
if (asPath === '/') { | ||
return ( | ||
<> | ||
<MainHeader /> | ||
<main className={`mt-[70px]`}>{children}</main> | ||
<Footer /> | ||
</> | ||
); | ||
} | ||
|
||
if (asPath === '/signin' || asPath === '/signup') { | ||
return ( | ||
<> | ||
<LogoHeader /> | ||
<main className="m-auto px-4 pb-20 pt-6 tablet:px-12 tablet:pb-24 desktop:px-16 desktop:pb-16"> | ||
{children} | ||
</main> | ||
</> | ||
); | ||
} | ||
|
||
return ( | ||
<> | ||
<MainHeader /> | ||
<main | ||
className={`m-auto mt-[70px] px-4 pb-24 pt-8 tablet:px-6 desktop:max-w-[1200px] desktop:px-0`} | ||
> | ||
{children} | ||
</main> | ||
</> | ||
); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import Image from 'next/image'; | ||
import Link from 'next/link'; | ||
|
||
export default function LogoHeader() { | ||
return ( | ||
<header className="flex justify-center pt-6 tablet:pt-12 desktop:pt-16"> | ||
<Link href="/"> | ||
<Image | ||
width={198} | ||
height={66} | ||
className="tablet:h-[132px] tablet:w-[396px]" | ||
src="/images/logo_big.svg" | ||
alt="판다마켓 로고" | ||
priority | ||
/> | ||
</Link> | ||
</header> | ||
); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.