Skip to content

Commit

Permalink
[조규진] Sprint10
Browse files Browse the repository at this point in the history
  • Loading branch information
gjrefa9139 committed Aug 16, 2024
1 parent 4c58233 commit c6f1e51
Show file tree
Hide file tree
Showing 49 changed files with 4,407 additions and 314 deletions.
21 changes: 15 additions & 6 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,24 @@

### 기본

- [x] 자유 게시판 페이지 주소는 “/boards” 입니다.
- [x] 전체 게시글에서 드롭 다운으로 “최신 순” 또는 “좋아요 순”을 선택해서 정렬을 할 수 있습니다.
- [x] 게시글 목록 조회 api를 사용하여 베스트 게시글, 게시글을 구현합니다.
- [ ] 게시글 title에 검색어가 일부 포함되면 검색이 됩니다.
#### 상품 등록 페이지

- [x] 상품 등록 페이지 주소는 “/addboard” 입니다.
- [x] 게시판 이미지는 최대 한개 업로드가 가능합니다.
- [x] 각 input의 placeholder 값을 정확히 입력해주세요.
- [x] 이미지를 제외하고 input 에 모든 값을 입력하면 ‘등록' 버튼이 활성화 됩니다.
- [ ] 회원가입, 로그인 api를 사용하여 받은 accessToken을 사용하여 게시물 등록을 합니다.
- [ ] ‘등록’ 버튼을 누르면 게시물 상세 페이지로 이동합니다.

#### 상품 상세 페이지

- [x] 상품 상세 페이지 주소는 “/board/{id}” 입니다.
- [ ] 댓글 input 값을 입력하면 ‘등록' 버튼이 활성화 됩니다.
- [ ] 활성화된 ‘등록' 버튼을 누르면 댓글이 등록됩니다

### 심화

- [ ] 반응형으로 보여지는 베스트 게시판 개수를 다르게 설정할때 서버에 보내는 pageSize값을 적절하게 설정합니다.
- [ ] next의 prefetch 기능을 사용해봅니다.
-

## 주요 변경사항

Expand Down
20 changes: 20 additions & 0 deletions UI/UI.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@import '../styles/config.scss';

.main {
margin-top: var(--header-height);
padding: 16px;

@include media($tablet) {
padding: 16px 24px;
}

@include media($pc) {
margin: var(--header-height) auto;
padding: 24px;
max-width: 1248px;
}
}

.auth {
max-width: 1248px;
}
11 changes: 6 additions & 5 deletions layout/index.tsx → UI/index.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { ReactNode } from 'react';
import Header from './Header';
import s from './UI.module.scss';
import GNB from './layout/GNB';
import { useRouter } from 'next/router';

type layout = {
children: ReactNode;
};

function Layout({ children }: layout) {
function UI({ children }: layout) {
const router = useRouter();
const isAuthPage = router.pathname === ('/login' || '/signup');

return (
<>
{!isAuthPage && <Header />}
<main style={!isAuthPage ? { marginTop: 'var(--header-height)' } : {}}>{children}</main>
{!isAuthPage && <GNB />}
<main className={!isAuthPage ? s.main : s.auth}>{children}</main>
</>
);
}

export default Layout;
export default UI;
61 changes: 61 additions & 0 deletions UI/layout/GNB.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
@import '../../styles/config.scss';

.wrap {
position: fixed;
top: 0;
z-index: 1;

width: 100%;
background-color: #fff;
border-bottom: 1px solid #dfdfdf;

.contain {
display: flex;
justify-content: space-between;
align-items: center;

max-width: 1600px;
height: var(--header-height);
padding: 0 16px;

nav {
display: flex;
list-style: none;
gap: 8px;
font-weight: bold;
font-size: 16px;
color: var(--gray600);
margin-left: 16px;
flex-grow: 1;

:hover {
color: var(--blue);
}
}

@include media($tablet) {
padding: 0 24px;

nav {
gap: 36px;
font-size: 18px;
margin-left: 20px;
}
}

@include media($pc) {
margin: auto;

nav {
margin-left: 32px;
}
}

.login {
font-size: 16px;
font-weight: 600;
border-radius: 8px;
padding: 14.5px 43px;
}
}
}
39 changes: 39 additions & 0 deletions UI/layout/GNB.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import s from './GNB.module.scss';
import logo from '@/public/logo/icon_logo.png';
import Image from 'next/image';
import Link from 'next/link';
import { useRouter } from 'next/router';

function GNB() {
const { pathname } = useRouter();

function getLinkStyle(isActive: boolean) {
return { color: isActive ? 'var(--blue)' : undefined };
}

return (
<header className={s.wrap}>
<div className={s.contain}>
<Link href='/' aria-label='홈으로 이동'>
<Image src={logo} alt='판다마켓 로고' />
</Link>

<nav>
<Link href='/boards' style={getLinkStyle(pathname === '/boards')}>
자유게시판
</Link>

<Link href='/items' style={getLinkStyle(pathname === ('/items' || '/additem'))}>
중고마켓
</Link>
</nav>

<Link href='/login' className={`button ${s.login}`}>
로그인
</Link>
</div>
</header>
);
}

export default GNB;
40 changes: 40 additions & 0 deletions api/articleApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export async function getArticleDetail(articleId: number) {
if (!articleId) {
throw new Error('Invalid article ID');
}

try {
const response = await fetch(`https://panda-market-api.vercel.app/articles/${articleId}`);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const body = await response.json();
return body;
} catch (error) {
console.error('Failed to fetch article detail:', error);
throw error;
}
}

export async function getArticleComments({ articleId, limit = 10 }: { articleId: number; limit?: number }) {
if (!articleId) {
throw new Error('Invalid article ID');
}

const params = {
limit: String(limit),
};

try {
const query = new URLSearchParams(params).toString();
const response = await fetch(`https://panda-market-api.vercel.app/articles/${articleId}/comments?${query}`);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const body = await response.json();
return body;
} catch (error) {
console.error('Failed to fetch article comments:', error);
throw error;
}
}
61 changes: 61 additions & 0 deletions api/itemApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
export async function getProducts({ orderBy, pageSize, page = 1 }: ProductListFetcherParams) {
const params = new URLSearchParams({
orderBy,
pageSize: String(pageSize),
page: String(page),
});

try {
const response = await fetch(`https://panda-market-api.vercel.app/products?${params}`);

if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const body = await response.json();
return body;
} catch (error) {
console.error('Failed to fetch products:', error);
throw error;
}
}

export async function getProductDetail(productId: number) {
if (!productId) {
throw new Error('Invalid product ID');
}

try {
const response = await fetch(`https://panda-market-api.vercel.app/products/${productId}`);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const body = await response.json();
return body;
} catch (error) {
console.error('Failed to fetch product detail:', error);
throw error;
}
}

export async function getProductComments({ productId, limit = 10 }: { productId: number; limit?: number }) {
if (!productId) {
throw new Error('Invalid product ID');
}

const params = {
limit: String(limit),
};

try {
const query = new URLSearchParams(params).toString();
const response = await fetch(`https://panda-market-api.vercel.app/products/${productId}/comments?${query}`);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const body = await response.json();
return body;
} catch (error) {
console.error('Failed to fetch product comments:', error);
throw error;
}
}
55 changes: 33 additions & 22 deletions components/AllPost.module.scss
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@
@import '../styles/config.scss';

.content {
display: flex;
gap: 8px;
min-height: 72px;
.wrap {
border-bottom: 1px solid var(--gray200);
padding-bottom: 24px;

h3 {
font-size: 18px;
font-weight: 600;
flex: 1;
.content {
display: flex;
min-height: 72px;
gap: 8px;

@include media($tablet) {
font-size: 20px;
h3 {
font-size: 18px;
font-weight: 600;
flex: 1;

@include media($tablet) {
font-size: 20px;
}
}
}

.thumbnail {
background-color: #fff;
border: 1px solid var(--gray200);
width: 72px;
height: 72px;
border-radius: 8px;
padding: 12px;
.thumbnail {
background-color: #fff;
border: 1px solid var(--gray200);
width: 72px;
height: 72px;
border-radius: 8px;
padding: 12px;

.img {
width: 100%;
height: 100%;
position: relative;
.img {
width: 100%;
height: 100%;
position: relative;
}
}
}
}
Expand Down Expand Up @@ -82,3 +87,9 @@
cursor: pointer;
}
}

.posts {
display: flex;
flex-direction: column;
gap: 24px;
}
Loading

0 comments on commit c6f1e51

Please sign in to comment.