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

[조규진] Sprint7 #224

Merged
Show file tree
Hide file tree
Changes from all 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
27 changes: 27 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-helmet-async": "^2.0.5",
"react-router-dom": "^6.23.1",
"react-scripts": "5.0.1",
"styled-components": "^6.1.11",
Expand Down
1 change: 1 addition & 0 deletions public/_redirects
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* /index.html 200
10 changes: 4 additions & 6 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,18 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://codeit8-sprint-mission-jgj.netlify.app/" />
<meta property="og:url" content="https://jgj-sprint.netlify.app/" />
<meta property="og:title" content="판다마켓" />
<meta property="og:image" content="%PUBLIC_URL%/og-image.png" />
<meta property="og:image" content="https://jgj-sprint.netlify.app/og-image.png" />
<meta property="og:description" content="일상의 모든 물건을 거래해 보세요" />
<title>판다마켓</title>
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="icon" href="favicon.ico" />
<link
rel="stylesheet"
as="style"
crossorigin
href="https://cdn.jsdelivr.net/gh/orioncactus/[email protected]/dist/web/static/pretendard.min.css" />
</head>

<body>
<div id="root"></div>
</body>
<body id="root"></body>
</html>
37 changes: 37 additions & 0 deletions src/API/itemApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,40 @@ export async function getProducts(params = {}) {
throw error;
}
}

export async function getProductDetail(productId) {
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, params }) {
if (!productId) {
throw new Error('Invalid product ID');
}

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;
}
}
Comment on lines +17 to +52
Copy link
Collaborator

Choose a reason for hiding this comment

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

url만 다른 함수 2개가 같은 동작을 하고있어서, 공통 함수로 분리하면 반복 코드를 줄일 수 있을것같네요

const fetchData =async(url)=>{
 try {
    const response = await fetch(url);
    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 getProductDetail(productId){
if (!productId) {
    throw new Error('Invalid product ID');
  }
const url = `https://panda-market-api.vercel.app/products/${productId}`
return fetchData(url)
}

export async function getProductComments({ productId, params }) {
if (!productId) {
    throw new Error('Invalid product ID');
  }
const query = new URLSearchParams(params).toString();
const url = `https://panda-market-api.vercel.app/products/${productId}/comments?${query}`
return fetchData(url)
}

15 changes: 14 additions & 1 deletion src/App.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
main {
margin-top: var(--header-height);
margin: var(--header-height) 16px;
}

@media (min-width: 768px) {
main {
margin: var(--header-height) 24px;
}
}

@media (min-width: 1280px) {
main {
max-width: 1200px;
margin: var(--header-height) auto;
}
}
25 changes: 0 additions & 25 deletions src/App.js

This file was deleted.

17 changes: 17 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Outlet } from 'react-router-dom';
import './App.css';
import Header from './Layout/Header.jsx';

function App() {
return (
<>
<Header />

<main>
<Outlet />
</main>
</>
);
}

export default App;
110 changes: 110 additions & 0 deletions src/Home/HomePage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { Helmet } from 'react-helmet-async';

function HomePage() {
return (
<>
<Helmet>
<title>판다마켓</title>
</Helmet>
<main>
<section class='banner hero'>
<div class='wrapper'>
<h2>
일상의 모든 물건을
<br />
거래해 보세요
</h2>
<a href='items.html' class='button pill'>
구경하러 가기
</a>
</div>
</section>

<section class='wrapper features'>
<div class='feature'>
<img src='images/home/feature1_hot_item.png' alt='인기 상품' />
<div class='feature-content'>
<h3>Hot Item</h3>
<h2>
인기 상품을
<br />
확인해 보세요
</h2>
<p class='feature-description'>
가장 HOT한 중고거래 물품을
<br />
판다마켓에서 확인해 보세요
</p>
</div>
</div>
<div class='feature'>
<img src='images/home/feature2_search.png' alt='검색 기능' />
<div class='feature-content'>
<h3>Search</h3>
<h2>
구매를 원하는
<br />
상품을 검색하세요
</h2>
<p class='feature-description'>
구매하고 싶은 물품은 검색해서
<br />
쉽게 찾아보세요
</p>
</div>
</div>
<div class='feature'>
<img src='images/home/feature3_register.png' alt='판매 상품 등록' />
<div class='feature-content'>
<h3>Register</h3>
<h2>
판매를 원하는
<br />
상품을 등록하세요
</h2>
<p class='feature-description'>
어떤 물건이든 판매하고 싶은 상품을
<br />
쉽게 등록하세요
</p>
</div>
</div>
</section>

<section class='banner bottom'>
<div class='wrapper'>
<h2>
믿을 수 있는
<br />
판다마켓 중고거래
</h2>
</div>
</section>
</main>

<footer>
<address>©codeit - 2024</address>
<div class='footer-menu'>
<a href='privacy.html'>Privacy Policy</a>
<a href='faq.html'>FAQ</a>
</div>
<nav class='social-media'>
<a href='https://www.facebook.com/' target='_blank' rel='noopener noreferrer'>
<img src='images\social\ic_facebook.png' alt='페이스북' width='20px' />
</a>
<a href='https://twitter.com/' target='_blank' rel='noopener noreferrer'>
<img src='images\social\ic_twitter.png' alt='트위터' width='20px' />
</a>
<a href='https://www.youtube.com/' target='_blank' rel='noopener noreferrer'>
<img src='images\social\ic_youtube.png' alt='유튜브' width='20px' />
</a>
<a href='https://www.instagram.com/' target='_blank' rel='noopener noreferrer'>
<img src='images\social\ic_instagram.png' alt='인스타그램' width='20px' />
</a>
</nav>
</footer>
</>
);
}

export default HomePage;
File renamed without changes.
25 changes: 24 additions & 1 deletion src/Layout/Header.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
.navLeft {
.globalHeader {
position: fixed;
top: 0;
width: 100%;
height: var(--header-height);
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 16px;
background-color: #fff;
border-bottom: 1px solid #dfdfdf;
z-index: 1;

:nth-child(2) {
flex-grow: 1;
}
}

.globalHeader nav ul {
Expand All @@ -25,6 +38,11 @@
}

@media (min-width: 768px) {
.globalHeader {
padding: 0 24px;
gap: 32px;
}

.globalHeader nav ul {
gap: 36px;
font-size: 18px;
Expand All @@ -33,6 +51,11 @@
}

@media (min-width: 1280px) {
.globalHeader {
padding: 0 200px;
gap: 32px;
}

.globalHeader nav ul {
margin-left: 32px;
}
Expand Down
44 changes: 25 additions & 19 deletions src/Layout/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,35 @@
import { Link, NavLink, useLocation } from 'react-router-dom';
import './Header.css';
import logo from '../logo.svg';

function Header() {
const location = useLocation();
const highlightCommunity = ({ isActive }) => (isActive ? { color: 'var(--blue)' } : {});
const highlightItems = ({ isActive }) =>
location.pathname === '/additem' || isActive ? { color: 'var(--blue)' } : {};

return (
<header className='globalHeader'>
<div className='navLeft'>
<a href='/' className='headerLogo' aria-label='홈으로 이동'>
<img src={logo} alt='판다마켓 로고' />
</a>

<nav>
<ul>
<li>
<a href='/community'>자유게시판</a>
</li>
<li>
<a href='/items'>중고마켓</a>
</li>
</ul>
</nav>
</div>

<a href='login' className='login button'>
<Link to='/' className='headerLogo' aria-label='홈으로 이동'>
<img src={logo} alt='판다마켓 로고' />
</Link>
<nav>
<ul>
<li>
<NavLink to='/community' style={highlightCommunity}>
Copy link
Collaborator

Choose a reason for hiding this comment

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

  • 인라인 스타일링은 지양하는게 좋습니다.
  • styled-component를 사용하면 component의 스타일링도 가능합니다.
import {NavLink} from 'react-router-dom'
import styled from 'styled-components'

const StyledNavLink = styled(NavLink)`
color : ${({isActive,theme})=>isActive? theme.colors.blue : undefined}
`

styled(NavLink) 이 부분에 인자로 스타일링 할 컴포넌트를 전달하는게 가능합니다 :-)
공식문서 Styling any component 를 참고 해 보세요! :-)

자유게시판
</NavLink>
</li>
<li>
<NavLink to='/items' style={highlightItems}>
중고마켓
</NavLink>
</li>
</ul>
</nav>
<Link to='/login' className='login button'>
로그인
</a>
</Link>
</header>
);
}
Expand Down
Loading
Loading