Skip to content
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
7 changes: 7 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 @@ -17,6 +17,7 @@
"@mui/material": "^7.1.0",
"axios": "^1.9.0",
"classnames": "^2.5.1",
"dayjs": "^1.11.13",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-router-dom": "^7.5.0",
Expand Down
6 changes: 6 additions & 0 deletions public/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.
Binary file added public/icons/ic_heart_fill.png
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 public/icons/ic_heart_fill.svg
Copy link
Collaborator

Choose a reason for hiding this comment

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

❗️ 수정요청
같은 이미지가 왜 다른 확장자로 두개 존재해야하는지 모르겠어요~

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 public/icons/ic_line.svg
Copy link
Collaborator

Choose a reason for hiding this comment

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

❗️ 수정요청
해당 요소를 굳이 이미지로 사용하신 특별한 이유가 있을까요? CSS로도 동일한 형태를 구현할 수 있어 불필요한 이미지일 것 같아요.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions public/icons/ic_setting.svg
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 public/images/Img_empty.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { globalStyles } from "./styles/GlobalStyle";
import ItemsLayout from "./components/ItemsLayout";
import Board from "./pages/Board";
import AddItem from "./pages/AddItem";
import ProductId from "./pages/ProductId";

function App() {
return (
Expand All @@ -27,6 +28,7 @@ function App() {
</Route>
<Route element={<ItemsLayout />}>
<Route path="/items" element={<Items />} />
<Route path="/items/:productId" element={<ProductId />} />
<Route path="/board" element={<Board />} />
<Route path="/additem" element={<AddItem />} />
</Route>
Expand Down
4 changes: 4 additions & 0 deletions src/api/axios.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ const RETRY_DELAY = 1000; // 재시도 간격 1초
baseAPI.interceptors.request.use(
(config) => {
// 요청이 보내지기 전에 작업 수행
const token = localStorage.getItem("accessToken");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
Expand Down
35 changes: 35 additions & 0 deletions src/api/commentAPI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import baseAPI from "./axios";

export const commentAPI = {
postComment: async (productId, content) => {
Comment on lines +3 to +4
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
commentAPI 객체명과 postComment 메소드명이 모두 “comment”를 포함해 불필요하게 중복되는 것 같아요. 이름에 대해 고민해보시면 좋겠어요~

try {
const response = await baseAPI.post(`/products/${productId}/comments`, {
content,
});
return response.data;
} catch (error) {
console.error("댓글 작성 실패", error);
throw new Error("댓글 작성 실패");
}
},
patchComment: async (commentId, content) => {
try {
const response = await baseAPI.patch(`/comments/${commentId}`, {
content,
});
return response.data;
} catch (error) {
console.error("댓글 수정 실패", error);
throw new Error("댓글 수정 실패");
}
},
deleteComment: async (commentId) => {
try {
const response = await baseAPI.delete(`/comments/${commentId}`);
return response.data;
} catch (error) {
console.error("댓글 삭제 실패", error);
throw new Error("댓글 삭제 실패");
}
},
};
15 changes: 15 additions & 0 deletions src/api/productCommentAPi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import baseAPI from "./axios";

export const productCommentAPI = {
getProductComment: async (productId, limit = 5, cursor = null) => {
try {
const response = await baseAPI.get(`/products/${productId}/comments`, {
params: { limit, cursor },
});
return response.data;
} catch (error) {
console.error("상품 댓글 불러오기 실패", error);
throw new Error("상품 댓글을 불러오는 데 실패했습니다.");
}
},
};
32 changes: 32 additions & 0 deletions src/api/productIdAPI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import baseAPI from "./axios";

export const productIdAPI = {
getProductId: async (productId) => {
try {
const response = await baseAPI.get(`/products/${productId}`);
return response.data;
} catch (error) {
console.error("상품 불러오기 실패", error);
throw new Error("상품을 불러오는 데 실패했습니다.");
}
},
// 추후 로그인 회원가입 기능으로 토큰 얻고 기능추가
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍 칭찬
주석한 이유에 대해 적어주신 것 좋습니다 👍

// postProductIdFavorite: async (productId) => {
// try {
// const response = await baseAPI.post(`/products/${productId}/favorite`);
// return response.data;
// } catch (error) {
// console.error("상품 좋아요 실패", error);
// throw new Error("상품 좋아요를 실패했습니다.");
// }
// },
// deleteProductIdFavorite: async (productId) => {
// try {
// const response = await baseAPI.delete(`/products/${productId}/favorite`);
// return response.data;
// } catch (error) {
// console.error("상품 좋아요 취소 실패", error);
// throw new Error("상품 좋아요 취소를 실패했습니다.");
// }
// },
};
13 changes: 9 additions & 4 deletions src/api/productsAPI.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import baseAPI from "./axios";

export const productsAPI = {
getProducts: async (page = 1, pageSize = 10, orderBy = "recent") => {
getProducts: async (
page = 1,
pageSize = 10,
orderBy = "recent",
keyword = ""
) => {
try {
const response = await baseAPI.get(`/products`, {
params: { page, pageSize, orderBy },
params: { page, pageSize, orderBy, keyword },
});
return response.data;
} catch (error) {
console.error("상품 불러오기 실패", error);
throw new Error("상품을 불러오는 데 실패했습니다.");
console.error("전체 상품 불러오기 실패", error);
throw new Error("전체 상품들을 불러오는 데 실패했습니다.");
}
},
};
33 changes: 28 additions & 5 deletions src/hooks/useProducts.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,52 @@
import { useState, useEffect } from "react";
import { productsAPI } from "@/api/productsAPI";

const useProducts = (page = 1, pageSize = 10, orderBy = "recent") => {
/**
* 상품 목록을 가져오는 커스텀 훅
* @param {number} page - 현재 페이지 번호 (기본값: 1)
* @param {number} pageSize - 한 페이지당 아이템 수 (기본값: 10)
* @param {string} orderBy - 정렬 기준 (기본값: "recent")
* @param {string} keyword - 검색어 (기본값: "")
*/

const useProducts = (
page = 1,
pageSize = 10,
orderBy = "recent",
keyword = ""
) => {
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [totalCount, setTotalCount] = useState(0); // 전체 아이템 수

useEffect(() => {
const fetchItems = async () => {
try {
const response = await productsAPI.getProducts(page, pageSize, orderBy);
setLoading(true);
const response = await productsAPI.getProducts(
page,
pageSize,
orderBy,
keyword
);
const itemsData = response.list || [];
const total = response.totalCount || 0; // 서버에서 totalCount도 내려줘야 함
setItems(itemsData);
setLoading(false);
setTotalCount(total);
setError(null);
} catch (err) {
console.error("상품 데이터 로딩 실패:", err);
setError(err.message);
} finally {
setLoading(false);
}
};

fetchItems();
}, [page, pageSize, orderBy]);
}, [page, pageSize, orderBy, keyword]);

return { items, loading, error };
return { items, totalCount, loading, error };
};

export default useProducts;
2 changes: 1 addition & 1 deletion src/pages/Items/components/AllItems/AllItems.styles.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { css } from "@emotion/react";
import { tablet, mobile } from "@/styles/utils/mixins";

export const AllItemsHeader = css`
export const AllItemsHeaderStyle = css`
display: flex;
align-items: center;
justify-content: space-between;
Expand Down
Loading
Loading