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

React 김주동 sprint7 #97

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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
# production
/build

# backup
/backups
.bak

# misc
.DS_Store
.env.local
Expand All @@ -21,3 +25,4 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.vercel
473 changes: 316 additions & 157 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
{
"name": "fe10-sprint-mission5",
"name": "fe10-sprint-mission7",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"date-fns": "^3.6.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.3",
"react-scripts": "5.0.1",
"react-spinners": "^0.13.8",
"styled-components": "^6.1.8",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand Down
39 changes: 0 additions & 39 deletions package.json.bak

This file was deleted.

2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="keywords" content="Codeit - FE10 Sprint Mission 5">
<meta name="keywords" content="Codeit - FE10 Sprint Mission 7">
<meta name="author" content="[email protected]">
<meta property="og:type" content="website" />
<meta property="og:title" content="판다마켓" />
Expand Down
3 changes: 3 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ import MarketPage from "./pages/MarketPage/MarketPage";
import AddItemPage from "./pages/AddItemPage/AddItemPage";
import CommunityFeedPage from "./pages/CommunityFeedPage/CommunityFeedPage";
import Header from "./components/Layout/Header";
import ItemPage from "./pages/ItemPage/ItemPage";

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

<div className="withHeader">
<Routes>
<Route index element={<HomePage />} />
<Route path="login" element={<LoginPage />} />
<Route path="items" element={<MarketPage />} />
<Route path="items/:productId" element={<ItemPage />} />
<Route path="additem" element={<AddItemPage />} />
<Route path="community" element={<CommunityFeedPage />} />
</Routes>
Expand Down
41 changes: 41 additions & 0 deletions src/api/itemApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,44 @@ 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;
}
}
4 changes: 4 additions & 0 deletions src/assets/images/icons/ic_back.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/assets/images/icons/ic_kebab.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.
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.
17 changes: 17 additions & 0 deletions src/assets/images/ui/empty-comments.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions src/assets/images/ui/ic_profile.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/components/Layout/Header.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
gap: 8px;
font-weight: bold;
font-size: 16px;
color: #4b5563;
color: var(--gray-600);
}

.globalHeader nav ul li a:hover {
Expand Down
41 changes: 25 additions & 16 deletions src/components/Layout/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,50 @@
import React from 'react'
import Logo from '../../assets/images/logo/logo.svg'
import { Link, NavLink } from 'react-router-dom'
import './Header.css'
import React from "react";
import Logo from "../../assets/images/logo/logo.svg";
import { Link, NavLink, useLocation } from "react-router-dom";
import "./Header.css";

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

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

return (
<header className='globalHeader'>
<div className='headerLeft'>
<Link to='/' className='headerLogo' aria-label='홈으로 이동'>
<img src={Logo} alt='판다마켓 로고' width='153' />
<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 to="/community" style={getLinkStyle}>
자유게시판
</NavLink>
</li>
<li>
<NavLink to='/items' style={getLinkStyle}>
<NavLink
to="/items"
style={({ isActive }) =>
location.pathname === "/additem" || isActive
? { color: "var(--blue)" }
: {}
}
>
중고마켓
</NavLink>
</li>
</ul>
</nav>
</div>

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

export default 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[400]};
width: 20px;
height: 20px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;

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

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 var(--gray-200);
border-radius: 12px;
padding: 9px;
margin-left: 8px;
}

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

.dropdownItem {
padding: 12px 44px;
border-bottom: 1px solid var(--gray-200);
font-size: 16px;
color: var(--gray-800);
cursor: pointer;
}

.dropdownItem:last-child {
border-bottom: none;
}
43 changes: 43 additions & 0 deletions src/components/UI/DropdownMenu.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, { useState } from "react";
import "./DropdownMenu.css";
import { ReactComponent as SortIcon } from "../../assets/images/icons/ic_sort.svg";

function DropdownMenu({ onSortSelection }) {
const [isDropdownVisible, setIsDropdownVisible] = useState(false);

const toggleDropdown = () => {
setIsDropdownVisible(!isDropdownVisible);
};

return (
<div className="sortButtonWrapper">
<button className="sortDropdownTriggerButton" onClick={toggleDropdown}>
<SortIcon />
</button>

{isDropdownVisible && (
<div className="dropdownMenu">
<div
className="dropdownItem"
onClick={() => {
onSortSelection("recent");
setIsDropdownVisible(false);
}}
Comment on lines +22 to +25
Copy link
Collaborator

@GANGYIKIM GANGYIKIM Sep 23, 2024

Choose a reason for hiding this comment

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

P2:
dropdown option들 모두 click 했을 때 새로 선택된 값 넘기고 안 보이게 해주는 로직이니 공통함수로 빼도 좋겠네요.

const onClick = (e) => {
 onSortSelection(e.target.value);
 setIsDropdownVisible(false);
}

...

<button type='button' value='recent' onClick={onClick}>최신순</button>
<button type='button' value='favorite' onClick={onClick}>인기순 </button>

>
최신순
</div>
<div
className="dropdownItem"
onClick={() => {
onSortSelection("favorite");
setIsDropdownVisible(false);
}}
>
인기순
</div>
</div>
)}
</div>
);
}
export default DropdownMenu;
Loading
Loading