-
Notifications
You must be signed in to change notification settings - Fork 78
[최윤석] Sprint9 #708
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
base: Next.js-최윤석
Are you sure you want to change the base?
The head ref may contain hidden characters: "Next.js-\uCD5C\uC724\uC11D-sprint9"
[최윤석] Sprint9 #708
Changes from all commits
93a0e93
b2e37bd
6f8bbb0
e11e25f
212e864
4dc5dd0
a4e278d
29fd1ad
ffc3ede
0d9413e
f8949b0
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,33 @@ | ||
import styles from "@/components/BestPost.module.css"; | ||
import { useEffect, useState } from "react"; | ||
import axios from "@/lib/axios"; | ||
import BestPostArticles from "./BestPostArticles"; | ||
|
||
export default function BestPost() { | ||
const [bestArticles, setBestArticles] = useState([]); | ||
|
||
async function getBestArticles() { | ||
try { | ||
const res = await axios.get("articles?page=1&pageSize=3&orderBy=like"); | ||
const nextArticles = res.data.list ?? []; | ||
setBestArticles(nextArticles); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
} | ||
|
||
useEffect(() => { | ||
getBestArticles(); | ||
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. 응답의 결과로 데이터가 업데이트된 경우에만 고려되고 있는데요.
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. 이러한 기능을 할 수 있는 커스텀 훅을 만들어보는 것도 좋은 것 같습니다. const { isLoading, isError, data } = useAsync(
() => getBestArticles(), // fetch 함수
[] // 의존성 배열
) |
||
}, []); | ||
|
||
return ( | ||
<section className={styles.bestPost}> | ||
<h1 className={styles.bestPostTitle}>베스트 게시글</h1> | ||
<ul className={styles.bestItems}> | ||
{bestArticles.map((item) => ( | ||
<BestPostArticles key={item.id} {...item} /> | ||
))} | ||
</ul> | ||
</section> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
.bestPost { | ||
width: 1200px; | ||
height: 217px; | ||
|
||
display: flex; | ||
flex-direction: column; | ||
justify-content: space-between; | ||
} | ||
|
||
.bestPostTitle { | ||
font-size: 20px; | ||
font-weight: 700; | ||
line-height: 23.87px; | ||
|
||
color: #111827; | ||
} | ||
|
||
.bestItems { | ||
width: 100%; | ||
height: 169px; | ||
|
||
display: grid; | ||
grid-template-rows: 169px; | ||
grid-template-columns: repeat(3, 384px); | ||
|
||
gap: 24px; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import styles from "@/components/BestPostArticles.module.css"; | ||
import Image from "next/image"; | ||
import medal from "@/public/ic_medal.png"; | ||
import heartIcon from "@/public/ic_heart.png"; | ||
|
||
export default function BestPostArticles({ | ||
title, | ||
image, | ||
likeCount, | ||
updatedAt, | ||
writer, | ||
}) { | ||
return ( | ||
<li className={styles.bestItem}> | ||
<div className={styles.bestItemWrap}> | ||
<div className={styles.badge}> | ||
<div className={styles.badgeWrap}> | ||
<Image src={medal} width={16} height={16} alt='메달 아이콘' /> | ||
<span>Best</span> | ||
</div> | ||
</div> | ||
<div className={styles.bestUserContents}> | ||
<h1 className={styles.bestTitle}>{title}</h1> | ||
{image ? ( | ||
<div className={styles.userProductImg}> | ||
<Image | ||
className={styles.productImg} | ||
width={48} | ||
height={44.57} | ||
src={image} | ||
alt='상품 이미지' | ||
/> | ||
</div> | ||
) : null} | ||
</div> | ||
<div className={styles.bestUserInfoWrap}> | ||
<div className={styles.bestUserInfo}> | ||
<span>{writer.nickname}</span> | ||
<div className={styles.bestUserCount}> | ||
<Image src={heartIcon} width={16} height={16} alt='하트 아이콘' /> | ||
<span className={styles.likeCount}>{likeCount}</span> | ||
</div> | ||
</div> | ||
<div className={styles.bestUserDate}> | ||
<span>{new Date(updatedAt).getFullYear()}</span> | ||
<span>. {new Date(updatedAt).getMonth() + 1}</span> | ||
<span>. {new Date(updatedAt).getDay()}</span> | ||
</div> | ||
</div> | ||
</div> | ||
</li> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
.bestItem { | ||
width: 384px; | ||
height: 169px; | ||
|
||
display: flex; | ||
justify-content: center; | ||
align-items: flex-start; | ||
|
||
background-color: #f9fafb; | ||
} | ||
|
||
.bestItemWrap { | ||
width: 336px; | ||
height: 153px; | ||
|
||
display: flex; | ||
flex-direction: column; | ||
justify-content: space-between; | ||
} | ||
|
||
.badge { | ||
width: 102px; | ||
height: 30px; | ||
|
||
display: flex; | ||
justify-content: center; | ||
|
||
background-color: #3692ff; | ||
border-radius: 0 0 32px 32px; | ||
} | ||
|
||
.badgeWrap { | ||
width: 54px; | ||
height: 24px; | ||
|
||
display: flex; | ||
align-items: center; | ||
gap: 4px; | ||
} | ||
|
||
.badgeWrap span { | ||
font-size: 16px; | ||
font-weight: 600; | ||
line-height: 24px; | ||
|
||
color: #fff; | ||
} | ||
|
||
.bestUserContents { | ||
width: 100%; | ||
|
||
display: flex; | ||
justify-content: space-between; | ||
} | ||
|
||
.bestTitle { | ||
display: inline; | ||
|
||
font-size: 20px; | ||
font-weight: 600; | ||
line-height: 23.87px; | ||
|
||
color: #1f2937; | ||
} | ||
|
||
.userProductImg { | ||
width: 71px; | ||
height: 71px; | ||
|
||
position: relative; | ||
|
||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
|
||
border: 1px solid #e5e7eb; | ||
} | ||
|
||
.productImg { | ||
width: 100%; | ||
height: auto; | ||
} | ||
|
||
.bestUserInfoWrap { | ||
width: 100%; | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: flex-end; | ||
} | ||
|
||
.bestUserInfo { | ||
width: auto; | ||
height: 17px; | ||
|
||
display: flex; | ||
align-items: flex-end; | ||
gap: 8px; | ||
|
||
font-size: 14px; | ||
font-weight: 400; | ||
line-height: 16.71px; | ||
|
||
color: #4b5563; | ||
} | ||
|
||
.bestUserCount { | ||
display: flex; | ||
align-items: center; | ||
gap: 4px; | ||
} | ||
|
||
.likeCount { | ||
color: #6b7280; | ||
} | ||
|
||
.bestUserDate { | ||
font-size: 14px; | ||
font-weight: 400; | ||
line-height: 16.71px; | ||
|
||
color: #4b5563; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import Link from "next/link"; | ||
import Image from "next/image"; | ||
import styles from "./Header.module.css"; | ||
import headerLogo from "../public/header-logo.png"; | ||
import signImg from "../public/sign-img.png"; | ||
|
||
export default function Header() { | ||
return ( | ||
<header className={styles.header}> | ||
<nav className={styles.nav}> | ||
<ul className={styles.menus}> | ||
<li className={styles.title}> | ||
<Image src={headerLogo} width={40} height={40} alt='로고' /> | ||
<h1>판다마켓</h1> | ||
</li> | ||
<li className={styles.links}> | ||
<Link className={styles.link} href='/boards'> | ||
자유게시판 | ||
</Link> | ||
<Link className={styles.link} href='/'> | ||
중고마켓 | ||
</Link> | ||
</li> | ||
</ul> | ||
<div> | ||
<Image src={signImg} width={40} height={40} alt='로그인 이미지' /> | ||
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.
|
||
</div> | ||
</nav> | ||
</header> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
.header { | ||
width: 100%; | ||
height: 70px; | ||
|
||
padding: 0 200px; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
|
||
border-bottom: 1px solid #dfdfdf; | ||
background-color: #fff; | ||
} | ||
|
||
.nav { | ||
width: 100%; | ||
height: 100%; | ||
|
||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
} | ||
|
||
.menus { | ||
display: flex; | ||
align-items: center; | ||
gap: 32px; | ||
} | ||
|
||
.title { | ||
width: 153px; | ||
|
||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
} | ||
|
||
.title h1 { | ||
font-size: 25.63px; | ||
font-weight: 700; | ||
line-height: 34.6px; | ||
|
||
color: #3692ff; | ||
} | ||
|
||
.links { | ||
width: 218px; | ||
display: flex; | ||
} | ||
|
||
.link { | ||
flex-grow: 1; | ||
|
||
font-size: 18px; | ||
font-weight: 700; | ||
line-height: 21.48px; | ||
|
||
color: #4b5563; | ||
} | ||
|
||
.link:nth-child(1) { | ||
color: #3692ff; | ||
} |
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.
아티클을 조회하는 API 함수를 만들어 분리하고, 이를 가져와서 사용하시는게 좋을 것 같습니다~!
(해당 함수는 API 요청만 처리하면 좋을 것 같아요.)