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

[송형진] Sprint5, Sprint6 #251

Merged
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
20 changes: 17 additions & 3 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,29 @@ import "./App.css";
import Header from "./components/layout/Header";
import BestProducts from "./components/BestProducts/BestProducts";
import AllProducts from "./components/AllProducts/AllProducts";
import { BrowserRouter } from "react-router-dom";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import AddItem from "./pages/AddItem";
import "./styles/global.css";

function MainContent() {
return (
<>
<BestProducts />
<AllProducts />
</>
);
}
Comment on lines +9 to +16
Copy link
Collaborator

Choose a reason for hiding this comment

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

보통 이렇게 되면 아에 파일을 새로 만들어서 나누긴 해요ㅎㅎ

근데 이렇게 써도 문제는 전혀 없어요~


function App() {
return (
<BrowserRouter>
<div className="App">
<Header />
<BestProducts />
<AllProducts />
<Routes>
<Route path="/" element={<MainContent />} />
<Route path="/items" element={<MainContent />} />
<Route path="pages/additem" element={<AddItem />} />
</Routes>
</div>
</BrowserRouter>
);
Expand Down
Binary file added src/assets/images/registerImage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 20 additions & 1 deletion src/components/AllProducts/AllProducts.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.all-item-section {
max-width: 1200px;
margin: 40px auto;
padding: 20px;
}

.all-item-header {
Expand All @@ -10,11 +11,29 @@
margin-bottom: 20px;
}

.all-product-list {
.all-product-list.desktop {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 20px;
list-style: none;
padding: 0;
margin: 0;
}

.all-product-list.tablet {
display: grid;
grid-template-columns: repeat(3, 1fr);
Comment on lines +24 to +25
Copy link
Collaborator

Choose a reason for hiding this comment

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

오.... grid 도 잘 사용하셨네요...!

gap: 20px;
list-style: none;
padding: 0;
margin: 0;
}

.all-product-list.mobile {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
list-style: none;
padding: 0;
margin: 0;
}
22 changes: 18 additions & 4 deletions src/components/AllProducts/AllProducts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,32 @@ import ProductItem from "../common/product";
import SearchForm from "../SearchForm/SearchForm";
import Pagination from "../Pagination/Pagination";
import "./AllProducts.css";
import useDevice from "../../hooks/useDevice";

function AllProducts() {
const [allItemList, setAllItemList] = useState([]);
const [selectedOption, setSelectedOption] = useState("recent");
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(0);
const [size, setSize] = useState(282);

const { mode } = useDevice();

useEffect(() => {
const fetchAllItems = async () => {
let pageSize = 10;
if (mode === "tablet") {
pageSize = 6;
setSize(221);
} else if (mode === "mobile") {
pageSize = 4;
setSize(168);
} else {
setSize(221);
}
Comment on lines +20 to +29
Copy link
Collaborator

Choose a reason for hiding this comment

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

혹시 useMemo 도 배우셨을까요?

보면 mode에 따라서 pageSize 는 항상 결정되어있어요.
그래서 mode에 따라서 pageSize를 정의하게되면 다음과 같이 쓸 수 있어요

const pageSize = useMemo(() => {
      if (mode === "tablet") {
            return 6;
      } else if (mode === "mobile") {
            return 4
      } else {
            return 10;
      }
}, []);

그치만 아직 안배운거라면 지금 상태로도 문제는 전혀 없어요ㅎㅎ!

const data = await getData({
page: currentPage,
pageSize: 10,
pageSize: pageSize,
orderBy: selectedOption,
});

Expand All @@ -24,7 +38,7 @@ function AllProducts() {
};

fetchAllItems();
}, [currentPage, selectedOption]);
}, [currentPage, selectedOption, mode]);

const handlePageChange = (pageNumber) => {
if (pageNumber < 1 || pageNumber > totalPages) return;
Expand All @@ -40,15 +54,15 @@ function AllProducts() {
setSelectedOption={setSelectedOption}
/>
</div>
<ul className="all-product-list">
<ul className={`all-product-list ${mode}`}>
{allItemList.map((item) => (
<li key={item.id}>
<ProductItem
imageUrl={item.images[0]}
name={item.name}
price={item.price}
likeCount={item.favoriteCount}
size={221}
size={size}
/>
</li>
))}
Expand Down
21 changes: 19 additions & 2 deletions src/components/BestProducts/BestProducts.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
.best-section {
margin: 0 auto;
width: 1200px;
padding: 20px;
max-width: 1200px;
}

.product-list {
.product-list.desktop {
display: flex;
flex-wrap: wrap;
gap: 20px;
Expand All @@ -14,3 +14,20 @@
padding: 0;
list-style: none;
}

.product-list.tablet {
display: flex;
flex-wrap: wrap;
gap: 24px;
justify-content: left;
margin: 0 auto;
padding: 0;
list-style: none;
}

.product-list.mobile {
display: flex;
justify-content: left;
padding: 0;
list-style: none;
}
24 changes: 20 additions & 4 deletions src/components/BestProducts/BestProducts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,44 @@ import { useState, useEffect } from "react";
import { getData } from "../../api";
import ProductItem from "../common/product";
import "./BestProducts.css";
import useDevice from "../../hooks/useDevice";

function BestProducts() {
const [itemList, setItemList] = useState([]);
const [currentPage, setCurrentPage] = useState(1);

const [size, setSize] = useState(282);

const { mode } = useDevice();

//베스트상품 가져오기
useEffect(() => {
const fetchBestItems = async () => {
let pageSize = 4;
if (mode === "tablet") {
pageSize = 2;
setSize(343);
} else if (mode === "mobile") {
pageSize = 1;
setSize(343);
} else {
setSize(282);
}

const data = await getData({
page: currentPage,
pageSize: 4,
pageSize: pageSize,
orderBy: "favorite",
});
setItemList(data.list);
};
fetchBestItems();
}, []); //베스트 상품은 pagination 없으니 일단 한번만 실행
}, [mode]); //베스트 상품은 pagination 없으니 일단 한번만 실행

return (
<section className="best-section">
<h2>베스트 상품</h2>
<ul className="product-list">
<ul className={`product-list ${mode}`}>
Copy link
Collaborator

Choose a reason for hiding this comment

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

이런것도 잘 이용하시네요ㅋㅋ
media query로 처리하는것보다 훨씬 좋을꺼에요!

{" "}
{itemList.map((item) => (
<li key={item.id}>
Expand All @@ -33,7 +49,7 @@ function BestProducts() {
name={item.name}
price={item.price}
likeCount={item.favoriteCount}
size={282}
size={size}
/>
</li>
))}
Expand Down
32 changes: 32 additions & 0 deletions src/components/SearchForm/SearchForm.css
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,35 @@
font-size: 14px;
cursor: pointer;
}

.search-container.tablet .search-input {
width: 242px;
}

.search-container.mobile .search-input {
width: 242px;
}

@media screen and (max-width: 768px) {
.search-form {
display: block;
align-items: center;
gap: 12px;
}

.search-button {
display: block;
}

.search-container {
top: 100px;
position: relative;
transform: translateX(-400px);
overflow-x: hidden; /* 가로 스크롤 방지 */
}

select {
position: relative;
top: 15px;
}
}
6 changes: 4 additions & 2 deletions src/components/SearchForm/SearchForm.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { Link } from "react-router-dom";
import searchImage from "../../assets/images/search.png";
import "./SearchForm.css";
import useDevice from "../../hooks/useDevice";

function SearchForm({ selectedOption, setSelectedOption }) {
const { mode } = useDevice();
return (
<form className="search-form">
<div className="search-container">
<div className={`search-container ${mode}`}>
<img src={searchImage} alt="검색" />
<input
type="text"
placeholder="검색할 상품을 입력해주세요"
className="search-input"
/>
</div>
<Link to="./pages/items.jsx">
<Link to="./pages/additem">
<button type="submit" className="search-button">
상품 등록하기
</button>
Expand Down
15 changes: 7 additions & 8 deletions src/components/common/product.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
@media screen and (min-width: 1200px) {
.heart-section {
display: flex;
gap: 6px;
}
.heart-section {
display: flex;
gap: 6px;
}
/* @media screen and (min-width: 768px) and (max-width: 1199px) {

.product-info span {
position: relative;
top: 5px;
}
@media screen and (min-width: 375px) and (max-width: 767px) {
} */
3 changes: 2 additions & 1 deletion src/components/common/product.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import "./product.css";
import heartImage from "../../assets/images/heart.png";
import useDevice from "../../hooks/useDevice";
Copy link
Collaborator

Choose a reason for hiding this comment

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

여기에서 useDevice 는 필요없을것같긴 해요...!ㅠ


function ProductItem({ imageUrl, name, price, likeCount, size }) {
return (
Expand All @@ -26,7 +27,7 @@ function ProductItem({ imageUrl, name, price, likeCount, size }) {
<p>{price.toLocaleString()}원</p>
<div className="heart-section">
<img src={heartImage} alt="하트이미지" />
<span>{likeCount}</span>
<span>{likeCount.toLocaleString()}</span>
</div>
</div>
</div>
Expand Down
18 changes: 15 additions & 3 deletions src/components/layout/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import userIcon from "../../assets/images/user.png";
import "./Header.css";
import { Link } from "react-router-dom";
import { Link, useLocation } from "react-router-dom";
function Header() {
const location = useLocation();
return (
<header className="main-header">
<div className="nav-container">
<a href="/">
<div className="brand-logo" />
</a>
<nav className="nav-links">
<Link to="./pages/items.jsx">자유게시판</Link>
<Link to="./pages/items.jsx">중고마켓</Link>
<Link to="./">자유게시판</Link>
<Link
to="./items"
style={{
color:
location.pathname === "/items" ||
location.pathname === "/pages/additem"
? "#3692ff"
: "none",
}}
>
중고마켓
</Link>
Comment on lines +13 to +25
Copy link
Collaborator

Choose a reason for hiding this comment

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

와... 진짜 디테일하게 잘 하셨네요!ㅎㅎ
진짜 잘 하셨어요ㅋㅋ

좀 더 나아가서... 만약에 메뉴가 여러개 더 추가된다고 생각해보면
style에 color를 처리하기위해서 5줄씩 추가가 되야할꺼에요ㅠ

메뉴 3개가 늘어나면 15줄이 추가되구요...

그럼 이부분을 따로 컴포넌트화 시켜놓는것도 방법일것같아요...!
to 값으로 받은것과 pathname 이 일치하는경우 색상을 변경하는 컴포넌트로요ㅎㅎ!

</nav>
</div>
<div className="user-profile">
Expand Down
22 changes: 22 additions & 0 deletions src/hooks/useDevice.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useState, useEffect } from "react";

const useDevice = () => {
const [windowWidth, setWindowWidth] = useState(window.innerWidth);

let mode = "desktop";

if (windowWidth < 1200 && windowWidth >= 768) mode = "tablet";
else if (windowWidth < 768) mode = "mobile";

useEffect(() => {
window.addEventListener("resize", (event) => {
setWindowWidth(event.target.innerWidth);
});
}, []);
Comment on lines +11 to +15
Copy link
Collaborator

Choose a reason for hiding this comment

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

이부분 조금 더 개선을 해보면...

useEffect의 첫번쨰 함수가 실행되는 시점은 조금 어렵게 말하면 mount 될떄 에요.
즉, 화면이 브라우저에 보여지는 순간을 의미해요

근데 상태가 바뀌는 등으로 인해 해당 컴포넌트가 다시 mount 되면 window에 resize 이벤트가 또 추가되게 되어요ㅠ

그래서 unmount 될때 기존에 달아주었던 이벤트를 잠깐 떼어주는게 필요해요ㅠ

그런 역할을 하는 코드가 useEffect에서 return 하는 함수에요

  useEffect(() => {
  const handleResize = (event) => {
      setWindowWidth(event.target.innerWidth);
    };

    window.addEventListener("resize", handleResize);

   return () => {
    window.removeEventListener("resize", handleResize);
   }
  }, []);


return {
mode,
};
};

export default useDevice;
Loading
Loading