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 #217

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
764aedf
스프린트 미션 1
jaewan0 May 27, 2024
e2d7c64
Merge pull request #24 from jaewan0/Basic-이재완-sprint8
201steve May 31, 2024
70a7194
Delete btn_image from images
jaewan0 May 31, 2024
07684b0
Rename file
jaewan0 May 31, 2024
5dcf5c9
Modify code
jaewan0 May 31, 2024
d8c4319
Add items, privacy, faq pages
jaewan0 May 31, 2024
9bcb9a0
Add login page
jaewan0 May 31, 2024
bee8a80
Add signup page
jaewan0 May 31, 2024
2ffb310
Add visibility button
jaewan0 May 31, 2024
ab92e9a
Fix Global Navigation Bar
jaewan0 May 31, 2024
f34de28
Merge pull request #50 from jaewan0/Basic-이재완-sprint2
201steve Jun 4, 2024
13e7ba7
Merge pull request #1 from codeit-bootcamp-frontend/Basic-이재완
jaewan0 Jun 7, 2024
08d7dc0
Apply template code
jaewan0 Jun 14, 2024
34f0455
create(signin.js): 로그인 페이지 자바스크립트 파일 생성
jaewan0 Jun 14, 2024
4ba75e7
feat(signin): input 값 유효성 검사 기능 추가
jaewan0 Jun 14, 2024
bfdb95e
feat(signup): input 값 유효성 검사 기능 추가
jaewan0 Jun 14, 2024
95b5403
feat(signup): 충돌 해결을 위한 커밋
jaewan0 Jun 17, 2024
932046e
Merge branch 'Basic-이재완' of https://github.com/jaewan0/8-Sprint-Missi…
jaewan0 Jun 27, 2024
bf13403
Apply template code
jaewan0 Jul 5, 2024
730f9d3
feat(Item): 상품 상세 페이지 구현(구조분해 오류)
jaewan0 Jul 5, 2024
4c91566
fix(Item): 구조분해 오류 해결
jaewan0 Jul 8, 2024
74d2f89
Resolve merge conflinct
jaewan0 Jul 8, 2024
930c6e4
add: .gitignore file 추가
arthurkimdev Jul 8, 2024
a6c3550
Remove node_modules from git cache
arthurkimdev Jul 8, 2024
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
26 changes: 26 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

# .env
.env
8,222 changes: 4,134 additions & 4,088 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "1-weekly-mission",
"name": "panda-market-react",
"version": "0.1.0",
"private": true,
"dependencies": {
Expand All @@ -8,7 +8,9 @@
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.3",
"react-scripts": "5.0.1",
"styled-components": "^6.1.8",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand Down
24 changes: 23 additions & 1 deletion public/index.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>판다마켓</title>

<!--
Font preloading
- 페이지가 처음 로딩될 때 텍스트가 순간적으로 깜빡이거나 바뀌는 듯한 현상을 보신 적이 있으신가요? (Flash of Unstyled Text, FOUT)
브라우저가 지정된 폰트를 다운로드 받는 동안 임시로 대체 폰트("fallback font")를 사용하기 때문인데요, 폰트를 preload하면 텍스트 렌더링을 보다 매끄럽게 할 수 있습니다.
- 브라우저는 rel="preload"로 지정된 리소스를 우선적으로 준비합니다.
- 폰트, 페이지 상단의 이미지, 가장 먼저 실행되어야 하는 스크립트 등에 preload 속성을 사용하는 경우가 많아요.
- href의 리소스 유형에 따라 <link>의 `as` 속성값을 정해야 해요. 일반적인 폰트 파일(예: .woff, .ttf 등)이라면 as="font"겠지만, 우리가 사용하는 웹폰트는 css 형식이기 때문에 as="style"을 사용합니다.
-->
<link
rel="preload"
href="https://cdn.jsdelivr.net/gh/orioncactus/[email protected]/dist/web/static/pretendard.min.css"
as="style"
onload="this.onload=null;this.rel='stylesheet'"
/>
<!-- 간혹 보안 등의 이슈로 자바스크립트를 지원하지 않는 브라우저 환경에서도 최소한의 스타일이 로딩될 수 있도록 합니다. -->
<noscript
><link
rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/orioncactus/[email protected]/dist/web/static/pretendard.min.css"
/></noscript>
</head>
<body>
<div id="root"></div>
Expand Down
53 changes: 25 additions & 28 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,11 @@
import { useState, useEffect } from "react";
import "./App.css";
import Nav from "./components/Nav";
import AllProductList from "./components/AllProductList";

async function getData() {
const url = "https://panda-market-api.vercel.app/products";
const response = await fetch(url);
const result = await response.json();

const data = result.list.map((items) => ({
id: items.id,
title: items.name,
description: items.description,
price: items.price,
image: items.images,
favoriteCount: items.favoriteCount,
createAt: items.createAt,
}));

return data;
}
import { BrowserRouter, Route, Routes } from "react-router-dom";
import HomePage from "./pages/HomePage/HomePage";
import LoginPage from "./pages/LoginPage/LoginPage";
import MarketPage from "./pages/MarketPage/MarketPage";
import AddItemPage from "./pages/AddItemPage/AddItemPage";
import ItemsPage from "./pages/Item/ItemsPage";
import CommunityFeedPage from "./pages/CommunityFeedPage/CommunityFeedPage";
import Header from "./components/Layout/Header";

function App() {
const [items, setItems] = useState([]);
Expand All @@ -33,13 +19,24 @@ function App() {
}, []);

return (
<>
<Nav />
<div className="product-lists">
<AllProductList className="all-product-list" items={items} />
<BrowserRouter>
{/* Global Navigation Bar */}
<Header />

<div className="withHeader">
<Routes>
{/* React Router v6부터는 path="/" 대신 간단하게 `index`라고 표기하면 돼요 */}
<Route index element={<HomePage />} />
<Route path="login" element={<LoginPage />} />
<Route path="additem" element={<AddItemPage />} />
<Route path="items" element={<ItemsPage />}>
<Route index element={<MarketPage />} />
<Route path=":productId" element={<ItemsPage />} />
</Route>
<Route path="community" element={<CommunityFeedPage />} />
</Routes>
</div>
;
</>
</BrowserRouter>
);
}

Expand Down
18 changes: 18 additions & 0 deletions src/api/itemApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export async function getProducts(params = {}) {
// URLSearchParams을 이용하면 파라미터 값을 자동으로 쉽게 인코딩할 수 있어요.
const query = new URLSearchParams(params).toString();

try {
const response = await fetch(
`https://panda-market-api.vercel.app/products?${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 products:", error);
throw error;
}
}
Comment on lines +1 to +18
Copy link
Collaborator

Choose a reason for hiding this comment

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

이게 API 요청이 여러개 될때 https://panda-market-api.vercel.app 값은 반복될 수 있어요.

해당 파일 상위에

const API_BASE_URL = 'https://panda-market-api.vercel.app/';

선언해서 공통 일괄 사용하는 방법이 좋겠습니다.

Binary file added src/assets/images/Img_inquiry_empty.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/images/icons/arrow_left.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/images/icons/arrow_right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/images/icons/ic_heart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/images/icons/ic_plus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/images/icons/ic_search.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/assets/images/icons/ic_sort.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/images/icons/ic_x.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/assets/images/logo/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions src/components/Layout/Header.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.headerLeft {
display: flex;
align-items: center;
}

.headerLogo {
margin-right: 16px;
}

.globalHeader nav ul {
display: flex;
list-style: none;
gap: 8px;
font-weight: bold;
font-size: 16px;
color: #4b5563;
}

.globalHeader nav ul li a:hover {
color: var(--blue);
}

.loginLink {
font-size: 16px;
font-weight: 600;
border-radius: 8px;
padding: 11.5px 23px;
}

@media (min-width: 768px) {
.globalHeader nav ul {
gap: 36px;
font-size: 18px;
}

.headerLogo {
margin-right: 35px;
}
}

@media (min-width: 1280px) {
.headerLogo {
margin-right: 47px;
}
}
53 changes: 53 additions & 0 deletions src/components/Layout/Header.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from "react";
import Logo from "../../assets/images/logo/logo.svg";
import { Link, NavLink, useLocation } from "react-router-dom";
import "./Header.css";

// react-router-dom의 NavLink를 이용하면 활성화된 네비게이션 항목을 하이라이트해줄 수 있어요!
function getLinkStyle({ isActive }) {
return { color: isActive ? "var(--blue)" : undefined };
}

function Header() {
const location = useLocation(); // 현재 경로 정보

return (
<header className="globalHeader">
<div className="headerLeft">
<Link to="/" className="headerLogo" aria-label="홈으로 이동">
<img src={Logo} alt="판다마켓 로고" width="153" />
</Link>

<nav>
<ul>
<li>
<NavLink to="/community" style={getLinkStyle}>
자유게시판
</NavLink>
</li>
<li>
{/* React Router v6 이전 버전에서는 NavLink `isActive` prop으로 바로 스타일 정보를 넣어줄 수 있었지만, 최신 버전에서는 className 또는 style을 이용해야 해요 */}
{/* /additem 페이지에서도 네이게이션의 '중고마켓' 링크 하이라이트 */}
<NavLink
to="/items"
style={({ isActive }) =>
location.pathname === "/additem" || isActive
? { color: "var(--blue)" }
: {}
}
>
중고마켓
</NavLink>
</li>
</ul>
</nav>
</div>

<Link to="/login" className="loginLink button">
로그인
</Link>
</header>
);
}

export default Header;
27 changes: 27 additions & 0 deletions src/components/UI/DeleteButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from "react";
import styled from "styled-components";
import { ReactComponent as CloseIcon } from "../../assets/images/icons/ic_x.svg";

const Button = styled.button`
background-color: ${({ theme }) => theme.colors.gray[0]};
width: 20px;
height: 20px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;

&:hover {
background-color: ${({ theme }) => theme.colors.blue[0]};
}
`;

function DeleteButton({ onClick, label }) {
return (
<Button aria-label={`${label} 삭제`} onClick={onClick}>
<CloseIcon />
</Button>
);
}

export default DeleteButton;
33 changes: 33 additions & 0 deletions src/components/UI/DropdownMenu.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.sortButtonWrapper {
position: relative;
}

.sortDropdownTriggerButton {
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 9px;
margin-left: 8px;
}

.dropdownMenu {
position: absolute;
top: 110%;
right: 0;
background: #fff;
border-radius: 8px;
border: 1px solid #e5e7eb;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
z-index: 99;
}

.dropdownItem {
padding: 12px 44px;
border-bottom: 1px solid #e5e7eb;
font-size: 16px;
color: #1f2937;
cursor: pointer;
}

.dropdownItem:last-child {
border-bottom: none;
}
Loading
Loading