Skip to content

Commit

Permalink
Merge pull request #594 from baehyunji/React-배현지-sprint7
Browse files Browse the repository at this point in the history
[배현지] Sprint7
  • Loading branch information
airman5573 authored Jun 16, 2024
2 parents f9b36ab + 51db926 commit 0b4e061
Show file tree
Hide file tree
Showing 53 changed files with 1,449 additions and 103 deletions.
35 changes: 32 additions & 3 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 @@ -6,6 +6,7 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.7.2",
"classnames": "^2.5.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
8 changes: 7 additions & 1 deletion src/Main.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import { BrowserRouter, Routes, Route } from "react-router-dom";
import App from "./components/App";
import App from "./components/ui/App";
import UsedMarketPage from "./pages/UsedMarketPage";
import ProductRagistrationPage from "./pages/ProductRagistrationPage";
import FreeBoardPage from "./pages/FreeBoardPage";
import ProductDetailedPage from "./pages/ProductDetailedPage";

function Main() {
return (
<BrowserRouter>
<App>
<Routes>
<Route path="/free" element={<FreeBoardPage />} />
<Route path="/items" element={<UsedMarketPage />} />
<Route path="/additem" element={<ProductRagistrationPage />} />
<Route path="/items/:productId" element={<ProductDetailedPage />} />
</Routes>
</App>
</BrowserRouter>
Expand Down
29 changes: 22 additions & 7 deletions src/api.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
export async function getProducts() {
const response = await fetch("https://panda-market-api.vercel.app/products/");
if (!response.ok) {
throw new Error("데이터를 불러오는데 실패했습니다");
}
const body = await response.json();
return body;
import axios from "axios";

const instance = axios.create({
baseURL: "https://panda-market-api.vercel.app",
timeout: 3000,
});

export async function getProducts(params = {}) {
const query = new URLSearchParams(params).toString();
const res = await instance.get(`/products?${query}`);
return res.data;
}

export async function getProduct(productId) {
const res = await instance.get(`/products/${productId}`);
return res.data;
}

export async function getComment({ productId, params }) {
const query = new URLSearchParams(params).toString();
const res = await instance.get(`/products/${productId}/comments?${query}`);
return res.data;
}
Binary file modified src/assets/arrow-down.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/arrow-left.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/arrow-right.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/back-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/heart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/userIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes.
File renamed without changes.
57 changes: 57 additions & 0 deletions src/components/container/ListContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import ProductListContainer from "../ui/ProductListContainer";
import { useState, useEffect } from "react";
import { getProducts } from "../../api";

function ListContainer() {
const [products, setProducts] = useState([]);
const [order, setOrder] = useState("createdAt");
const [favoriteProducts, setFavoriteProducts] = useState([]);
const [searchText, setSearchText] = useState("");

const sortedProducts = products.sort((a, b) => b[order] - a[order]);

const loadList = async () => {
try {
const { list } = await getProducts();
setProducts(list);
} catch (e) {
if (e.response) {
console.log(e.response.status);
console.log(e.response.data);
} else {
console.log("리퀘스트가 실패했습니다.");
}
}
};

useEffect(() => {
loadList();
}, [order]);

useEffect(() => {
const sortedFavoriteProducts = [...products].sort(
(a, b) => b.favoriteCount - a.favoriteCount
);
setFavoriteProducts(sortedFavoriteProducts);
}, [products]);

const handleToggleClick = (option) => {
if (option === "newest") {
setOrder("createdAt");
} else if (option === "likes") {
setOrder("favoriteCount");
}
};

return (
<ProductListContainer
favoriteProducts={favoriteProducts}
sortedProducts={sortedProducts}
searchText={searchText}
handleToggleClick={handleToggleClick}
setSearchText={setSearchText}
/>
);
}

export default ListContainer;
8 changes: 8 additions & 0 deletions src/components/container/PaginationContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// import { getProducts } from "../../api";
// import PaginationBar from "../ui/PaginationBar";

function PaginationContainer() {
return;
}

export default PaginationContainer;
57 changes: 57 additions & 0 deletions src/components/container/ProductDeatilsContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import ProductDetails from "../ui/ProductDetails";
import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";
import { getProduct, getComment } from "../../api";
import CommentDetails from "../ui/CommentDetails";

function ProductDetailsContainer() {
const { productId } = useParams();
const [product, setProduct] = useState(null);
const [comments, setComments] = useState([]);

useEffect(() => {
const detailedProduct = async () => {
try {
const productData = await getProduct(productId);
setProduct(productData);
} catch (e) {
if (e.response) {
console.log(e.response.status);
console.log(e.response.data);
} else {
console.log("리퀘스트가 실패했습니다.");
}
}
};

const detailedComment = async () => {
const params = { limit: 3 };
try {
const commentData = await getComment({ productId, params });
setComments(commentData.list);
} catch (e) {
if (e.response) {
console.log(e.response.status);
console.log(e.response.data);
} else {
console.log("리퀘스트가 실패했습니다.");
}
}
};
detailedComment();
detailedProduct();
}, [productId]);

if (!product) {
return <div>로딩중</div>;
}

return (
<>
<ProductDetails product={product} />
<CommentDetails comments={comments} />
</>
);
}

export default ProductDetailsContainer;
46 changes: 46 additions & 0 deletions src/components/container/RagistrationContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import RagistrationForm from "../ui/RagistrationForm";
import { useState } from "react";

function RagistrationContainer() {
const [values, setValues] = useState({
imageFile: null,
productName: "",
productDescription: "",
productPrice: "",
productTag: "",
});

const handleChange = (name, value) => {
setValues((prevValues) => ({
...prevValues,
[name]: value,
}));
};

const handleInputChange = (e) => {
const { name, value } = e.target;
handleChange(name, value);
};

const handleSubmit = (e) => {
e.preventDefault();

setValues({
imageFile: null,
productName: "",
productDescription: "",
productPrice: "",
productTag: "",
});
};
return (
<RagistrationForm
values={values}
handleChange={handleChange}
handleInputChange={handleInputChange}
handleSubmit={handleSubmit}
/>
);
}

export default RagistrationContainer;
27 changes: 27 additions & 0 deletions src/components/container/ToggleMenuContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useCallback, useEffect, useState } from "react";
import ToggleMenu from "../ui/ToggleMenu";

function ToggleMenuContainer({ onClick }) {
const [isOpen, setIsOpen] = useState(false);

const onToggleMenu = useCallback((e) => {
e.stopPropagation();
setIsOpen((nextIsOpen) => !nextIsOpen);
}, []);

useEffect(() => {
if (!isOpen) return;

const handleClickOutside = () => setIsOpen(false);
window.addEventListener("click", handleClickOutside);

return () => {
window.removeEventListener("click", handleClickOutside);
};
}, [isOpen]);
return (
<ToggleMenu onToggleMenu={onToggleMenu} onClick={onClick} isOpen={isOpen} />
);
}

export default ToggleMenuContainer;
File renamed without changes.
26 changes: 23 additions & 3 deletions src/components/App.module.css → src/components/ui/App.module.css
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
@import-normalize; /* bring in normalize.css styles */
@import-normalize;

* {
box-sizing: border-box;
word-break: keep-all;
font-family: "Pretendard";
font-size: 16px;
font-weight: 400;
color: #1f2937;
}

html {
overflow-y: scroll;
background-color: #f9f9f9;
background-color: #fcfcfc;
}

body {
margin: 0;
}

a {
color: #494949;
text-decoration: none;
color: #4b5563;
}

:global(#root) {
Expand All @@ -33,3 +36,20 @@ a {
width: 100%;
margin: 0 auto;
}

button {
border: none;
cursor: pointer;
}

@media (max-width: 1199px) {
.body {
padding: 0 24px;
}
}

@media (max-width: 767px) {
.body {
padding: 0 16px;
}
}
Loading

0 comments on commit 0b4e061

Please sign in to comment.