SingleProductPage.jsx
import { useState } from "react";
import "./SingleProductPage.css";
const product = {
id: 1,
title: "상품 타이틀",
description:
"Lorem ipsum dolor sit amet, consectetur adipisicing elit. Maxime aliquid rerum a? Fugiat soluta facilis deleniti voluptatibus ab architecto dolores a, vero, beatae veniam error doloribus quia laudantium? Error fuga consequuntur quia accusantium? Consequatur modi laboriosam saepe culpa, ab atque.",
price: 9900,
images: [
],
stock: 10,
};
const SingleProductPage = () => {
//처음 시작 이미지 번호는 0임 -> product.images[0] = image1 을 의미함
const [selectedImage, setSelectedImage] = useState(0);
return (
<section className="align_center single_product">
<div className="align_center">
<div className="single_product_thumbnails">
{/* product 안의 images를 map 반복한다. */}
{product.images.map((image, index) => (
<img
src={image}
alt={product.title}
// css 는 selectedImage state가 index일 경우 selected_image 적용한다.
className={selectedImage === index ? "selected_image" : ""}
// 클릭하면 index로 스테이트 저장
onClick={() => setSelectedImage(index)}
/>
))}
</div>
<img
// 이미지는 선택된 index의 이미지로 출력한다.
src={product.images[selectedImage]}
alt={product.title}
className="single_product_display"
/>
</div>
<div className="single_product_details"></div>
</section>
);
};
export default SingleProductPage;
SingleProductPage.jsx
.single_product {
justify-content: center;
padding: 32px 48px;
}
.single_product_thumbnails {
display: flex;
flex-direction: column;
flex-wrap: wrap;
gap: 14px;
padding: 8px;
margin: 16px;
}
.single_product_thumbnails img {
width: 80px;
height: 80px;
object-fit: cover;
border-radius: 5px;
cursor: pointer;
transition: all 0.2s ease-in-out;
}
.single_product_display {
width: 600px;
height: 600px;
object-fit: cover;
border-radius: 10px;
}
.selected_image {
transform: scale(1.12);
}
App.jsx
<main>
{/* <HomePage /> */}
{/* <ProductsPage /> */}
<SingleProductPage />
</main>
그리고 사진 옆에 상품의 디테일을 추가한다.
(테스트)데이터로 사용할 product 객체를 샘플로 하나 만든다.
안에는 아래와 같이 id, title, description(상세정보) , price(가격), images(이미지 링크), stock 수량
import { useState } from "react";
import "./SingleProductPage.css";
const product = {
id: 1,
title: "상품 타이틀",
description:
"Lorem ipsum dolor sit amet, consectetur adipisicing elit. Maxime aliquid rerum a? Fugiat soluta facilis deleniti voluptatibus ab architecto dolores a, vero, beatae veniam error doloribus quia laudantium? Error fuga consequuntur quia accusantium? Consequatur modi laboriosam saepe culpa, ab atque.",
price: 9900,
images: [
],
stock: 10,
};
const SingleProductPage = () => {
const [selectedImage, setSelectedImage] = useState(0);
return (
<section className="align_center single_product">
<div className="align_center">
<div className="single_product_thumbnails">
{/* product 안의 images를 map 반복한다. */}
{product.images.map((image, index) => (
<img
src={image}
alt={product.title}
// css 는 selectedImage state가 index일 경우 selected_image 적용한다.
className={selectedImage === index ? "selected_image" : ""}
// 클릭하면 index로 스테이트 저장
onClick={() => setSelectedImage(index)}
/>
))}
</div>
<img
// 이미지는 선택된 index의 이미지로 출력한다.
src={product.images[selectedImage]}
alt={product.title}
className="single_product_display"
/>
</div>
{/* 상품 디테일 */}
<div className="single_product_details">
<h1 className="single_product_title">{product.title}</h1>
<p className="single_product_description">{product.description}</p>
<p className="single_product_price">
₩ {product.price.toLocaleString("ko-KR")} 원
</p>
<h2 className="quantity_title">구매개수:</h2>
<div className="align_center quantity_input">
{/* <QuantityInput /> */}
</div>
<button className="search_button add_cart">장바구니 추가</button>
</div>
</section>
);
};
export default SingleProductPage;
SingleProductPage.css
/* 상품 디테일 */
.single_product_details {
width: 35%;
padding: 16px 24px;
}
.single_product_title {
margin-bottom: 16px;
font-size: 32px;
}
.single_product_description {
margin-bottom: 16px;
line-height: 1.4;
}
.single_product_price {
margin-bottom: 16px;
font-size: 24px;
font-weight: 600;
}
.quantity_title {
font-size: 20px;
font-weight: 700;
margin-bottom: 3px;
}
.quantity_input {
font-size: 20px;
font-weight: 700;
margin: 5px 0 16px;
}
.add_cart {
width: fit-content;
padding: 8px 18px;
}
그리고 상품 수량을 표시할 QuantityInput 컴포넌트를 생성한다.
QuantityInput.jsx
import "./QuantityInput.css";
const QuantityInput = () => {
return (
<>
<button className="quantity_input_button" disabled>
{" "}
-{" "}
</button>
<p className="quantity_input_count">1</p>
<button className="quantity_input_button"> + </button>
</>
);
};
export default QuantityInput;
QuantityInput.css
.quantity_input_button {
width: 35px;
height: 35px;
font-size: 25px;
background-color: #ff8848;
color: #fff;
border: none;
border-radius: 100%;
cursor: pointer;
}
.quantity_input_button:disabled {
opacity: 0.3;
cursor: default;
}
.quantity_input_count {
margin: 0 40px;
text-align: center;
}
SingleProductPage.jsx에서 컴포넌트 적용한다.
<h2 className="quantity_title">구매개수:</h2>
<div className="align_center quantity_input">
<QuantityInput />
</div>
'FRONTEND > React' 카테고리의 다른 글
[myCart] 주문 내역 페이지 (0) | 2023.12.19 |
---|---|
[myCart] 장바구니 페이지 (0) | 2023.12.19 |
[myCart] 상품페이지 생성 (사이드 바/ 상품 목록) (0) | 2023.12.19 |
[myCart] FeaturedProducts 컴포넌트 및 ProductCard 컴포넌트 재사용 (0) | 2023.12.19 |
[myCart] 홈페이지 생성 및 heroSection 컴포넌트 재사용 (0) | 2023.12.19 |