diff --git a/src/api.js b/src/api.js index 1376dd2e..71613305 100644 --- a/src/api.js +++ b/src/api.js @@ -7,6 +7,7 @@ * @returns */ export async function getItems( + page = 1, pageSize = 10, orderBy = "recent", @@ -36,3 +37,5 @@ export async function addItem(requestBody) { return response; } + + diff --git a/src/components/BestList.js b/src/components/BestList.js new file mode 100644 index 00000000..2749d00f --- /dev/null +++ b/src/components/BestList.js @@ -0,0 +1,32 @@ +import { useEffect, useState } from "react"; +import { getItems } from "../api"; +import Card from "./Card"; +import style from "./BestList.module.css"; + +function BestList() { + const [cardList, setCardList] = useState([]); + + const fetchData = async function () { + const data = await getItems(1, 4, "favorite"); + setCardList(data.list); + }; + + useEffect(() => { + fetchData(); + }, []); + + return ( +
+
+
베스트 상품
+
+ {cardList.map((item) => { + return ; + })} +
+
+
+ ); +} + +export default BestList; diff --git a/src/components/BestList.module.css b/src/components/BestList.module.css new file mode 100644 index 00000000..e6c2c08b --- /dev/null +++ b/src/components/BestList.module.css @@ -0,0 +1,31 @@ +@font-face { + font-family: "Pretendard Variable"; + src: url("../../public/Pretendard-Regular.ttf"); +} + +.label { + font-family: "Pretendard Variable"; + font-size: 20px; + font-weight: 700; + line-height: 32px; + text-align: left; + color: #111827; +} + +.bestList { + display: flex; + justify-content: center; + gap: 24px; +} + +.bestListBlock { + display: flex; + flex-direction: column; + gap: 16px; + width: fit-content; +} + +.wrapper { + display: flex; + justify-content: center; +} diff --git a/src/components/Card.js b/src/components/Card.js new file mode 100644 index 00000000..d41953ba --- /dev/null +++ b/src/components/Card.js @@ -0,0 +1,24 @@ +import style from "./Card.module.css"; +import Favorite from "./Favorite"; + +function Card({ item, imgSize }) { + const { favoriteCount, images, price, name } = item; + const addDefaultImg = (e) => {e.currentTarget.src = "/images/free-icon-no-pictures-3875148.png"} + return ( +
+ {name} +
+
{name}
+
{price}
+ +
+
+ ); +} + +export default Card; diff --git a/src/components/Card.module.css b/src/components/Card.module.css new file mode 100644 index 00000000..813eb718 --- /dev/null +++ b/src/components/Card.module.css @@ -0,0 +1,41 @@ +@font-face { + font-family: "Pretendard Variable"; + src: url("../../public/Pretendard-Regular.ttf"); +} + +.cardImg { + border-radius: 16px; +} + +.card, +.cardTxt { + display: flex; + flex-direction: column; +} + +.card { + gap: 16px; +} + +.cardTxt { + gap: 6px; + font-family: "Pretendard Variable"; +} + +.title { + font-size: 14px; + font-weight: 500; + line-height: 24px; +} + +.price { + font-size: 16px; + font-weight: 700; + line-height: 26px; +} + +.favorite { + font-size: 12px; + font-weight: 500; + line-height: 18px; +} diff --git a/src/components/Favorite.js b/src/components/Favorite.js new file mode 100644 index 00000000..0f67c1b0 --- /dev/null +++ b/src/components/Favorite.js @@ -0,0 +1,12 @@ +import style from "./Favorite.module.css"; + +function Favorite({ favoriteCount }) { + return ( +
+ +
{favoriteCount}
+
+ ); +} + +export default Favorite; diff --git a/src/components/Favorite.module.css b/src/components/Favorite.module.css new file mode 100644 index 00000000..1c59d408 --- /dev/null +++ b/src/components/Favorite.module.css @@ -0,0 +1,4 @@ +.favorite { + display: flex; + gap: 4px; +} diff --git a/src/components/ItemList.js b/src/components/ItemList.js new file mode 100644 index 00000000..47de490f --- /dev/null +++ b/src/components/ItemList.js @@ -0,0 +1,145 @@ +import { useEffect, useState } from "react"; +import { getItems } from "../api"; +import Card from "./Card"; +import style from "./ItemList.module.css"; +import SearchBar from "./SearchBar"; + +function ItemList() { + const pagesToShow = 5; + const [cardList, setCardList] = useState([]); + const [order, setOrder] = useState("recent"); + const [totalCount, setTotalCount] = useState(0); + const [currentPage, setCurrentPage] = useState(1); // 현재 페이지 상태 + const [displayedPages, setDisplayedPages] = useState([]); + const [totalPages, setTotalPages] = useState(0); + const fetchData = async function (page) { + const data = await getItems(page, 10, order); + // data = totalCount 외 아이템 리스트들을 가지고있는 정보 + setTotalCount(data.totalCount); + setCardList(data.list); + setTotalPages(Math.ceil(totalCount / 10)); + }; + + const updateDisplayedPages = () => { + const start = Math.floor((currentPage - 1) / pagesToShow) * pagesToShow + 1; + const end = Math.min(start + pagesToShow - 1, totalPages); + console.log("start ", start); + console.log("end ", end); + console.log(Array.from({ length: end - start + 1 }, (_, i) => start + i)); + setDisplayedPages( + Array.from({ length: end - start + 1 }, (_, i) => start + i) + ); + console.log("displayedPages: ", displayedPages); + }; + + const handlePageChange = (page) => { + if (page < 1 || page > totalPages) return; // 범위를 넘어가는 경우 무시 + setCurrentPage(page); + fetchData(page); + // 여기서 getItems를 호출하여 아이템을 가져올 수 있습니다. + // const data = await getItems(page, itemsPerPage); + }; + + const handleNextPages = () => { + const nextPage = Math.min(currentPage + pagesToShow, totalPages); + setCurrentPage(nextPage); + }; + + const handlePreviousPages = () => { + const prevPage = Math.max(currentPage - pagesToShow, 1); + setCurrentPage(prevPage); + }; + + useEffect(() => { + fetchData(); + updateDisplayedPages(); + console.log(currentPage); + }, [order, totalCount, currentPage, totalPages]); + + // function handlePageChange(e) { + // // console.log(e); + // fetchData(e.target.value); + // } + + return ( + <> + +
+
+
전체 상품
+
+ {cardList.map((item) => { + return ( + + ); + })} +
+
+
+
+ + {displayedPages.map((page) => ( + + ))} + +
+ + ); +} + +export default ItemList; + +/** + * + * 1. 함수를 만드는데, 토탈카운트 나누기 10 하는 함수를 만듬 + * + * 2. 1번의 함수 리턴값에 따라서, 페이지 개수를 분리하는 기능을 만듬 ( 예를들면, 1~5 / 6~10 / 11~15 ...) + * + * 3. 1번의 함수 리턴값이 5 이상일때, 밑 + * + */ + +// function pageMake(totalCount) { +// // 146 +// const pageNumber = Math.ceil(totalCount / 10); // 15 +// const pageGroup = Array(pageNumber / 5) //[1,2,3] +// .fill() +// .map((el, i) => i + 1); +// // 0; // 0 -> 1 -> 2 + +// const pageNumberList = Array(pageNumber) // [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] +// .fill() +// .map((el, i) => i + 1); + +// const startPage = 0 + pageGroup * 5; +// const endPage = a.length + pageGroup * 5; + +// pageGroup.map((el, i) => { +// pageNumberList.slice(startPage, endPage); // 0,5 +// }); +// } diff --git a/src/components/ItemList.module.css b/src/components/ItemList.module.css new file mode 100644 index 00000000..5003ebf5 --- /dev/null +++ b/src/components/ItemList.module.css @@ -0,0 +1,31 @@ +@font-face { + font-family: "Pretendard Variable"; + src: url("../../public/Pretendard-Regular.ttf"); +} + +.label { + font-family: "Pretendard Variable"; + font-size: 20px; + font-weight: 700; + line-height: 32px; + text-align: left; + color: #111827; +} + +.itemList { + display: grid; + grid-template-columns: repeat(5, 1fr); /* 5개의 열 설정 */ + gap: 24px; +} + +.itemListBlock { + display: flex; + flex-direction: column; + gap: 16px; + width: fit-content; +} + +.wrapper { + display: flex; + justify-content: center; +} diff --git a/src/components/SearchBar.js b/src/components/SearchBar.js new file mode 100644 index 00000000..657bd220 --- /dev/null +++ b/src/components/SearchBar.js @@ -0,0 +1,26 @@ +import { useEffect, useState } from "react"; +import style from "./SearchBar.module.css"; + + +function SearchBar({ handleOrder }) { + const handleChange = (e) => { + handleOrder(e.target.value); + }; + return ( +
+ + +
+ +
+
+ ); +} + +export default SearchBar; diff --git a/src/components/SearchBar.module.css b/src/components/SearchBar.module.css new file mode 100644 index 00000000..4721651a --- /dev/null +++ b/src/components/SearchBar.module.css @@ -0,0 +1,31 @@ +.btnStyle { + color: #f3f4f6; + background-color: #3692ff; + border: 1px solid; + border-radius: 8px; +} + +.utilBox { + display: flex; + justify-content: flex-end; +} + +.searchBar { + width: 325px; + height: 42px; + border-radius: 12px; + border: 1px solid #f3f4f6; + background-color: #f3f4f6; + padding-left: 16px; +} + +.searchBar::placeholder { + background-image: url(https://cdn1.iconfinder.com/data/icons/hawcons/32/698627-icon-111-search-256.png); + background-position: 0px center; + background-size: 24px; + background-repeat: no-repeat; + text-indent: 24px; +} + +.dropBox { +} diff --git a/src/main.js b/src/main.js index ee63f682..aad9400d 100644 --- a/src/main.js +++ b/src/main.js @@ -3,6 +3,7 @@ import App from "./components/App"; import ItemPage from "./pages/ItemPage"; import AddItemPage from "./pages/AddItemPage"; + function Main() { return (