-
Notifications
You must be signed in to change notification settings - Fork 79
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
[고한샘] sprint10 #663
base: main
Are you sure you want to change the base?
The head ref may contain hidden characters: "Next.js-\uACE0\uD55C\uC0D8-sprint10"
[고한샘] sprint10 #663
Changes from all commits
87e3f15
1472169
671d4d5
14baca2
8d163dd
cf2e3df
398ac6c
a04698a
8f535bd
921aec0
f56d696
2ee994e
d80a89a
5d76a22
6f12196
6cdee27
af57418
c0b2b55
c5cd127
069ebed
c59c0eb
365a414
b690f65
d3bb2bb
eb445b0
b3d39fd
fbb8fcf
270af41
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "next/core-web-vitals" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). | ||
|
||
## Getting Started | ||
|
||
First, run the development server: | ||
|
||
```bash | ||
npm run dev | ||
# or | ||
yarn dev | ||
# or | ||
pnpm dev | ||
# or | ||
bun dev | ||
``` | ||
|
||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. | ||
|
||
You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. | ||
|
||
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. | ||
|
||
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. | ||
|
||
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. | ||
|
||
## Learn More | ||
|
||
To learn more about Next.js, take a look at the following resources: | ||
|
||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. | ||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. | ||
|
||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! | ||
|
||
## Deploy on Vercel | ||
|
||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. | ||
|
||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
.write { | ||
width: 84px; | ||
height: 42px; | ||
border-radius: 8px; | ||
background-color: #3692ff; | ||
font-family: Pretendard; | ||
font-size: 16px; | ||
font-weight: 600; | ||
color: #ffffff; | ||
text-align: center; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
border: none; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import styles from "@/components/BlueButton.module.css"; | ||
|
||
export default function BlueButton({ type = "", children }) { | ||
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. 타입스크립트를 사용한다면 타입을 꼭 지정해주세요! |
||
return ( | ||
<button type={type} className={styles.write}> | ||
{children} | ||
</button> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import React from "react"; | ||
|
||
interface Article { | ||
id?: number; | ||
title?: string; | ||
content?: string; | ||
} | ||
|
||
interface BoardItemProps { | ||
article: Article; | ||
} | ||
|
||
const BoardItem: React.FC<BoardItemProps> = ({ article }) => { | ||
return ( | ||
<div> | ||
<h2>{article.title}</h2> | ||
<p>{article.content}</p> | ||
</div> | ||
); | ||
}; | ||
|
||
export default BoardItem; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
.container { | ||
width: 100%; | ||
max-width: 1020px; | ||
margin-right: auto; | ||
margin-left: auto; | ||
} | ||
|
||
.page.container { | ||
margin-top: 80px; | ||
margin-bottom: 80px; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import styles from "@/components/Container.module.css"; | ||
import React from "react"; | ||
|
||
interface ContainerProps { | ||
className?: string; | ||
page?: boolean; | ||
children: React.ReactNode; | ||
} | ||
|
||
const Container: React.FC<ContainerProps> = ({ | ||
className = "", | ||
page = false, | ||
children, | ||
}) => { | ||
const classNames = `${styles.container} ${ | ||
page ? styles.page : "" | ||
} ${className}`; | ||
|
||
return <div className={classNames}>{children}</div>; | ||
}; | ||
export default Container; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import React, { useState } from "react"; | ||
|
||
interface DropDownProps { | ||
order?: string; | ||
onChangeOrder: (order: string) => void; | ||
} | ||
|
||
const DropDown: React.FC<DropDownProps> = ({ | ||
order = "recent", | ||
onChangeOrder, | ||
}) => { | ||
const [isDropDown, setIsDropDown] = useState(false); | ||
const [localOrder, setLocalOrder] = useState(order); | ||
|
||
const handleDropDown = () => { | ||
setIsDropDown(!isDropDown); | ||
}; | ||
const handleOptionClick = (order: string) => { | ||
setLocalOrder(order); | ||
onChangeOrder(order); | ||
setIsDropDown(false); | ||
}; | ||
|
||
return ( | ||
<> | ||
<div onClick={handleDropDown}> | ||
{localOrder == "recent" ? "최신순" : "좋아요순"} | ||
</div> | ||
{isDropDown && ( | ||
<div> | ||
<div onClick={() => handleOptionClick("recent")}>최신순</div> | ||
<div onClick={() => handleOptionClick("like")}>좋아요순</div> | ||
</div> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export default DropDown; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
.header { | ||
padding: 0 200px; | ||
height: 70px; | ||
border-bottom: 1px solid #dfdfdf; | ||
position: fixed; | ||
top: 0; | ||
left: 0; | ||
max-width: 1920px; | ||
z-index: 1000; | ||
width: 100%; | ||
background-color: white; | ||
} | ||
|
||
.container { | ||
display: flex; | ||
|
||
align-items: center; | ||
justify-content: space-between; | ||
} | ||
|
||
.leftNav { | ||
display: flex; | ||
align-items: center; | ||
justify-content: space-between; | ||
gap: 33px; | ||
} | ||
|
||
.leftNav div { | ||
font-family: Pretendard; | ||
font-size: 18px; | ||
font-weight: 700; | ||
line-height: 21.48px; | ||
text-align: center; | ||
} | ||
|
||
.rightNav { | ||
display: flex; | ||
align-items: center; | ||
justify-content: space-between; | ||
gap: 12px; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import Link from "next/link"; | ||
import styles from "./Header.module.css"; | ||
import Container from "./Container"; | ||
import Image from "next/image"; | ||
|
||
export default function Header() { | ||
return ( | ||
<header className={styles.header}> | ||
<Container className={styles.container}> | ||
<div className={styles.leftNav}> | ||
<Link href="/"> | ||
<Image | ||
src="/icon/header-logoIcon.png" | ||
alt="Home Logo" | ||
width={153} | ||
height={51} | ||
priority | ||
/> | ||
</Link> | ||
<Link href="/boards"> | ||
<div>자유게시판</div> | ||
</Link> | ||
<Link href="/market"> | ||
<div>중고마켓</div> | ||
</Link> | ||
</div> | ||
<div className={styles.rightNav}> | ||
<Link href="/join"> | ||
<Image | ||
src="/icon/profile-login-icon.png" | ||
alt="user profile" | ||
width={40} | ||
height={40} | ||
/> | ||
</Link> | ||
<Link href="/setting"> | ||
<div>설정</div> | ||
</Link> | ||
</div> | ||
</Container> | ||
</header> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { useRouter } from "next/router"; | ||
import { ChangeEvent, FormEvent, useState } from "react"; | ||
|
||
interface SearchFormProps { | ||
keyword?: string; | ||
onChangeKeyword?: (keyword: string) => void; | ||
} | ||
|
||
const SearchForm: React.FC<SearchFormProps> = ({ | ||
keyword = "", | ||
onChangeKeyword, | ||
}) => { | ||
const [value, setValue] = useState(keyword); | ||
const router = useRouter(); | ||
|
||
const handleChange = (e: ChangeEvent<HTMLInputElement>) => { | ||
setValue(e.target.value); | ||
}; | ||
|
||
const handleSubmit = (e: FormEvent<HTMLFormElement>) => { | ||
e.preventDefault(); | ||
|
||
if (!value) { | ||
router.push("/boards"); | ||
onChangeKeyword(" "); | ||
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. empty string이 아니라 공백으로 처리하는게 맞나요? |
||
return; | ||
} | ||
if (onChangeKeyword) { | ||
onChangeKeyword(value); | ||
} | ||
router.push(`boards?keyword=${value}`); | ||
}; | ||
return ( | ||
<form onSubmit={handleSubmit}> | ||
<input name="keyword" value={value} onChange={handleChange} /> | ||
<button type="submit">검색</button> | ||
</form> | ||
); | ||
}; | ||
|
||
export default SearchForm; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { createContext, useContext, useEffect, useState } from "react"; | ||
|
||
export const ThemeContext = createContext(); | ||
|
||
export default function ThemeProvider({ children }) { | ||
const [theme, setTheme] = useState("white"); | ||
useEffect(() => { | ||
document.body.classList.add(theme); | ||
return () => { | ||
document.body.classList.remove(theme); | ||
}; | ||
}, [theme]); | ||
|
||
return ( | ||
<ThemeContext.Provider value={{ theme, setTheme }}> | ||
{children} | ||
</ThemeContext.Provider> | ||
); | ||
} | ||
|
||
export function useTheme() { | ||
const themeContext = useContext(ThemeContext); | ||
if (!themeContext) { | ||
throw new Error("ThemeContext 안에서 써야 합니다."); | ||
} | ||
return themeContext; | ||
} |
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; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = { | ||
reactStrictMode: true, | ||
} | ||
|
||
module.exports = nextConfig |
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.
해당 버튼에만
Pretendard
가 적용되어야 하나요?그런게 아니라면 font는 최상위 node에서 사용하는게 좋을것 같습니다 ㅎ