From 1d8d7155cdb28cc7d5113072eb4633336939a64a Mon Sep 17 00:00:00 2001 From: Gabin Lee Date: Wed, 27 Nov 2024 16:32:59 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20=EB=A9=94=EC=9D=B8=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20api=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/product.ts | 11 +- src/components/ProfilePage/ProductList.tsx | 4 +- src/components/common/ProductComponent1.tsx | 32 +++-- src/pages/Main/BookmarkPage/BookmarkPage.tsx | 4 +- src/pages/Main/MainPage/MainPage.style.ts | 3 + src/pages/Main/MainPage/MainPage.tsx | 127 ++++++++----------- src/pages/Main/SearchPage/SearchPage.tsx | 119 +++++++---------- 7 files changed, 138 insertions(+), 162 deletions(-) diff --git a/src/api/product.ts b/src/api/product.ts index cb0ff5c..7dd4a02 100644 --- a/src/api/product.ts +++ b/src/api/product.ts @@ -1 +1,10 @@ -export {}; +import { client } from './client'; + +export const getAllProduct = async () => { + try { + const res = await client.get(`/product`); + return res.data; + } catch (error) { + throw error; + } +}; \ No newline at end of file diff --git a/src/components/ProfilePage/ProductList.tsx b/src/components/ProfilePage/ProductList.tsx index 0e89303..0afefb9 100644 --- a/src/components/ProfilePage/ProductList.tsx +++ b/src/components/ProfilePage/ProductList.tsx @@ -14,7 +14,7 @@ const ProductList = () => { return ( - { price={productData.price} imageURL={productData.imageURL} bookmarkedData={productData.bookmarked} - /> + /> */} ); diff --git a/src/components/common/ProductComponent1.tsx b/src/components/common/ProductComponent1.tsx index 0d193d5..fbfb1da 100644 --- a/src/components/common/ProductComponent1.tsx +++ b/src/components/common/ProductComponent1.tsx @@ -2,27 +2,35 @@ import React, { useState } from 'react'; import * as S from "../common/ProductComponent1.style"; import { ReactComponent as UnfilledBookmark } from '../../assets/common/ProductComponent1/bookmark_unfilled.svg'; import { ReactComponent as FilledBookmark } from '../../assets/common/ProductComponent1/bookmark_filled.svg'; +import { useNavigate } from 'react-router-dom'; -interface ProductProps { - title: string; - term: number; +export interface ProductProps { + productName: string; + duration: number; price: number; - imageURL: string; - bookmarkedData: boolean; + isMarked: boolean; + productId: number; + // imageURL: string; } -const ProductComponent1 = ({ title, term, price, imageURL, bookmarkedData }: ProductProps) => { - const [bookmarked, setBookmarked] = useState(bookmarkedData); +const ProductComponent1 = ({ productName, duration, price, isMarked, productId }: ProductProps) => { + const [bookmarked, setBookmarked] = useState(isMarked); + const navigate = useNavigate(); - const toggleBookmark = () => { + const toggleBookmark = (e: React.MouseEvent) => { + e.stopPropagation(); setBookmarked(prev => !prev); } + + const handleNavigate = () => { + navigate(`/product/${productId}`); + }; return ( - - - {title} - 제작 소요 기간 {term}일 + + + {productName} + 제작 소요 기간 {duration}일 {price.toLocaleString()}원 {bookmarked ? ( diff --git a/src/pages/Main/BookmarkPage/BookmarkPage.tsx b/src/pages/Main/BookmarkPage/BookmarkPage.tsx index 30bc762..e5affe5 100644 --- a/src/pages/Main/BookmarkPage/BookmarkPage.tsx +++ b/src/pages/Main/BookmarkPage/BookmarkPage.tsx @@ -19,7 +19,7 @@ const BookmarkPage = () => {
- {/* 이거 나중에 map으로 꼭 바꿔라 ;; */} + {/* 이거 나중에 map으로 꼭 바꿔라 ;; { price={productData.price} imageURL={productData.imageURL} bookmarkedData={productData.bookmarked} - /> + /> */} diff --git a/src/pages/Main/MainPage/MainPage.style.ts b/src/pages/Main/MainPage/MainPage.style.ts index 5cba3c3..9b995a1 100644 --- a/src/pages/Main/MainPage/MainPage.style.ts +++ b/src/pages/Main/MainPage/MainPage.style.ts @@ -40,6 +40,7 @@ export const Contents = styled.div` grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: 1rem; width: 100%; + min-height: 850px; justify-content: center; overflow-y: auto; margin-top: calc(8rem); @@ -50,4 +51,6 @@ export const Contents = styled.div` &::-webkit-scrollbar { display: none; } + + align-content: start; `; diff --git a/src/pages/Main/MainPage/MainPage.tsx b/src/pages/Main/MainPage/MainPage.tsx index 8133ffd..0623d8e 100644 --- a/src/pages/Main/MainPage/MainPage.tsx +++ b/src/pages/Main/MainPage/MainPage.tsx @@ -1,18 +1,54 @@ +import React, { useState, useEffect } from 'react'; import NavBar from '../../../components/common/NavBar'; import ProductComponent1 from '../../../components/common/ProductComponent1'; import Header from '../../../components/MainPage/Header'; import Filter from '../../../components/MainPage/Filter'; -import { useNavigate } from 'react-router-dom'; import * as S from './MainPage.style'; +import { getAllProduct } from '../../../api/product'; -const MainPage = () => { - const productData = { - title: "청바지를 활용한 텀블러 가방", - term: 3, +export interface ProductProps { + key: number; + duration: number; + isMarked: boolean; + nickname: string; + price: number; + productId: number; + productName: string; +} + +const productDummyData: ProductProps[] = [ + { + key: 0, + duration: 3, + isMarked: false, + nickname: "뉴진스", price: 20000, - imageURL: "", - bookmarked: false, - }; + productId: 1, + productName: "청바지를 활용한 텀블러 가방", + // imageURL: "", + }, +]; + +const MainPage = () => { + const [productList, setProductList] = useState([]); + + useEffect(() => { + const getProductList = async () => { + try { + const response = await getAllProduct(); + if (!response || response.length === 0) { + setProductList(productDummyData); + } else { + setProductList(response); + } + } catch (error) { + console.error(error); + setProductList(productDummyData); + } + }; + + getProductList(); + }, []); return ( @@ -21,70 +57,17 @@ const MainPage = () => { - {/* 이거 나중에 map으로 꼭 바꿔라 ;; */} - - - - - - - - - + {productList.map((product, index) => ( + + ))} diff --git a/src/pages/Main/SearchPage/SearchPage.tsx b/src/pages/Main/SearchPage/SearchPage.tsx index 7a268e7..14c2c4b 100644 --- a/src/pages/Main/SearchPage/SearchPage.tsx +++ b/src/pages/Main/SearchPage/SearchPage.tsx @@ -1,89 +1,62 @@ +import React, { useState, useEffect } from 'react'; import NavBar from '../../../components/common/NavBar'; import ProductComponent1 from '../../../components/common/ProductComponent1'; import SearchBar from '../../../components/SearchPage/SearchBar'; import { useNavigate } from 'react-router-dom'; import * as S from './SearchPage.style'; +import { getAllProduct } from '../../../api/product'; +import type { ProductProps } from '../../../components/common/ProductComponent1'; -const SearchPage = () => { - const productData = { - title: "청바지를 활용한 텀블러 가방", - term: 3, +const productDummyData: ProductProps[] = [ + { + duration: 3, + isMarked: false, price: 20000, - imageURL: "", - bookmarked: false, - }; + productName: "청바지를 활용한 텀블러 가방", + // imageURL: "", + productId: 1, + }, +]; + +const SearchPage = () => { + const [productList, setProductList] = useState([]); + + useEffect(() => { + const getProductList = async () => { + try { + const response = await getAllProduct(); + if (!response || response.length === 0) { + setProductList(productDummyData); + } else { + setProductList(response); + console.log(response); + } + } catch (error) { + console.error(error); + setProductList(productDummyData); + } + }; + + getProductList(); + }, []); return ( - - {/* 이거 나중에 map으로 꼭 바꿔라 ;; */} - - - - - - - - - - + {/* + {productList.map((product, index) => ( + + ))} + */} From 4d27e20bded1292942784ce3ac4b519757c5d1f6 Mon Sep 17 00:00:00 2001 From: Gabin Lee Date: Wed, 27 Nov 2024 17:29:06 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=E2=9C=A8=20=EC=A0=9C=ED=92=88=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20api=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/product.ts | 9 ++ .../ProductDetailPage/ProductDetailPage.tsx | 109 ++++++++++++++---- 2 files changed, 93 insertions(+), 25 deletions(-) diff --git a/src/api/product.ts b/src/api/product.ts index 7dd4a02..7ab7024 100644 --- a/src/api/product.ts +++ b/src/api/product.ts @@ -7,4 +7,13 @@ export const getAllProduct = async () => { } catch (error) { throw error; } +}; + +export const getProductDetail = async (productId: string) => { + try { + const res = await client.get(`/product/${productId}`); + return res.data; + } catch (error) { + throw error; + } }; \ No newline at end of file diff --git a/src/pages/Product/ProductDetailPage/ProductDetailPage.tsx b/src/pages/Product/ProductDetailPage/ProductDetailPage.tsx index f9e6bad..7f3aabc 100644 --- a/src/pages/Product/ProductDetailPage/ProductDetailPage.tsx +++ b/src/pages/Product/ProductDetailPage/ProductDetailPage.tsx @@ -1,10 +1,35 @@ import * as S from './ProductDetailPage.style'; -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import ProductImage from '../../../components/ProductDetailPage/ProductImage'; import DetailContent from '../../../components/ProductDetailPage/DetailContent'; import ReviewContent from '../../../components/ProductDetailPage/ReviewContent'; import Footer from '../../../components/ProductDetailPage/Footer'; import { OrderModal } from '../../../components/ProductDetailPage/OrderModal'; +import { getProductDetail } from '../../../api/product'; +import { useParams } from 'react-router-dom'; + +interface ProductProps { + productId: number; + userId: number; + sellerNickname: string; + productName: string; + isMarked: boolean; + price: number; + content: string; + duration: number; + rating: number; + productState: string; + deliveryFee: number; + materialInfo: string; + buyerNotice: string; + options: Option[]; +} + +interface Option { + optionId: number; + optionName: string; + optionPrice: number; +} const ProductImgData = { reviewImg1: "", @@ -12,26 +37,60 @@ const ProductImgData = { reviewImg3: "", reviewImg4: "", reviewImg5: "", -} +}; -const ProductData = { - userName: "이끼끼상점", - title: "양말목 지구 네임택", - price: 3000, - material: "양말 한 켤레", - period: 3, - bio: "버려지는 양말목에 새로운 쓰임을 불어넣어드립니다. 환경을 생각하는 나만의 잇아이템을 이끼끼 상점에서 만나보세요. 지구 네임택은 가방이나 열쇠에 달면 정말 예뻐요! 수수수수퍼노바 노바 캔스탑 하이퍼 스텔라 원초 그걸 찾아", -} +const productDummyData: ProductProps[] = [ + { + productId: 1, + userId: 1, + sellerNickname: "이화여대1886", + productName: "더미데이터 리사이클링", + isMarked: false, + price: 18000, + content: "더미데이터입니다 대충 설명란임", + duration: 1, + rating: 0, + productState: "ON_SALE", + deliveryFee: 3000, + materialInfo: "이 제품은 오직 ", + buyerNotice: "배송이 늦어질 수 있습니다.", + options: [ + { optionId: 1, optionName: "L 사이즈", optionPrice: 3000 }, + { optionId: 2, optionName: "M 사이즈", optionPrice: 2000 }, + { optionId: 3, optionName: "S 사이즈", optionPrice: 1000 }, + ], + }, +]; const ProductDetailPage = () => { const [isOrderModalOpen, setIsOrderModalOpen] = useState(false); + const [productInfo, setProductInfo] = useState(null); + + const { productId } = useParams() as { productId: string }; + + useEffect(() => { + const getProductInfo = async () => { + try { + const response = await getProductDetail(productId); + console.log(response) + if (!response || response.length === 0) { + setProductInfo(productDummyData[0]); + } else { + setProductInfo(Array.isArray(response) ? response[0] : response); + } + } catch (error) { + console.error(error); + setProductInfo(productDummyData[0]); + } + }; + + getProductInfo(); + }, []); - // 구매하기 버튼 클릭 핸들러 const handlePurchaseClick = () => { setIsOrderModalOpen(true); }; - // 모달 닫기 핸들러 const handleModalClose = () => { setIsOrderModalOpen(false); }; @@ -45,21 +104,21 @@ const ProductDetailPage = () => { reviewImg4={ProductImgData.reviewImg4} reviewImg5={ProductImgData.reviewImg5} /> - - -