Skip to content

Commit

Permalink
feat(Sprint7): itemDetail 페이지 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
wonsik3686 committed Jul 6, 2024
1 parent 417f694 commit 2127560
Show file tree
Hide file tree
Showing 33 changed files with 803 additions and 10 deletions.
22 changes: 22 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 @@ -11,6 +11,7 @@
"react-dom": "^18.2.0",
"react-router-dom": "^6.23.1",
"react-scripts": "5.0.1",
"sass": "^1.77.6",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand Down
2 changes: 2 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Privacy from './pages/privacy/Privacy';
import Items from './pages/items/Items';
import AddItems from './pages/addItems/AddItems';
import NavigationBar from './components/navigationBar/NavigationBar';
import ItemDetail from './pages/itemDetail/ItemDetail';
import './styles/global.css';

function App() {
Expand All @@ -22,6 +23,7 @@ function App() {
<Route path="items">
<Route index element={<Items />} />
<Route path="additems" element={<AddItems />} />
<Route path=":productId" element={<ItemDetail />} />
</Route>
<Route path="additems" element={<AddItems />} />
</Routes>
Expand Down
6 changes: 6 additions & 0 deletions src/assets/images/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.
6 changes: 4 additions & 2 deletions src/assets/images/icons/ic_heart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions src/assets/images/icons/ic_inquiry_empty.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 14 additions & 1 deletion src/components/items/BestItems/BestItems.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import './BestItems.css';
import { useEffect, useState } from 'react';
import Item from '../Item/Item';
import { getProducts } from '../../../pages/api/Items';
import { useNavigate } from 'react-router-dom';

const getPageSize = () => {
const width = window.innerWidth;
Expand All @@ -24,6 +25,7 @@ function BestItems() {
const [keyword, setKeyword] = useState('');
// 에러
const [fetchingError, setfetchingError] = useState(null);
const navigate = useNavigate();

const fetchItemList = async ({ order, page, pageSize, keyword }) => {
try {
Expand All @@ -35,10 +37,17 @@ function BestItems() {
setfetchingError(err);
}
};

const handleResize = () => {
setPageSize(getPageSize());
};

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

navigate(`/items/${e.currentTarget.dataset.itemId}`);
};

useEffect(() => {
window.addEventListener('resize', handleResize);
fetchItemList({ order, page, pageSize, keyword });
Expand All @@ -56,7 +65,11 @@ function BestItems() {
<div className="list-best-items">
{fetchingError && fetchingError.message}
{itemList?.map((item) => (
<Item item={item} key={`best-item-${item.id}`} />
<Item
item={item}
key={`best-item-${item.id}`}
handleClick={handleClickItem}
/>
))}
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/components/items/Item/Item.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import React from 'react';
import { ReactComponent as IconHeart } from '../../../assets/images/icons/ic_heart.svg';
import ImgDefault from '../../../assets/images/market/img_default.png';

function Item({ item }) {
function Item({ item, handleClick = () => {} }) {
const handleErrorImage = (e) => {
e.target.src = ImgDefault;
};

return (
<div className="wrapper-item">
<div className="wrapper-item" onClick={handleClick} data-item-id={item.id}>
<img
src={item.images[0]}
alt={item.name}
Expand Down
66 changes: 66 additions & 0 deletions src/components/items/ItemInfo/ItemInfo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import FavoriteButton from '../../../core/ui/buttons/FavoriteButton/FavoriteButton';
import ImageCard from '../../../core/ui/cards/ImageCard/ImageCard';
import HorizontalLine from '../../../core/ui/lines/HorizontalLine/HorizontalLine';
import TagList from '../../../core/ui/tags/TagList/TagList';
import styles from './ItemInfo.module.scss';

function ItemInfo({
itemImgSrc = '',
itemTitle = '',
itemPrice = 0,
itemDesc = '',
itemTags = [],
itemFavoriteCount = 0,
}) {
return (
<>
<div className={styles['item-info']}>
<div className={styles['item-info__img']}>
<ImageCard
imageSrc={itemImgSrc}
ImgDeafault={
'https://static.remove.bg/sample-gallery/graphics/bird-thumbnail.jpg'
}
isRoundEdged={true}
/>
</div>
<div className={styles['item-info__content']}>
<div>
<div>
<div>
<p className={styles['item-info__title']}>{itemTitle}</p>
</div>
<div>
<p className={styles['item-info__price']}>{`${itemPrice}원`}</p>
</div>
</div>
<HorizontalLine />
<div>
<div>
<p className={styles['item-info__content-title']}>
{'상품 소개'}
</p>
</div>
<div>
<p className={styles['item-info__desc-content']}>{itemDesc}</p>
</div>
<div className={styles['item-info__content-title']}>
{'상품 태그'}
</div>
<div>
<TagList tags={itemTags} isSharpVisible={true} />
</div>
</div>
</div>
<div>
<div>
<FavoriteButton initCount={itemFavoriteCount} />
</div>
</div>
</div>
</div>
</>
);
}

export default ItemInfo;
53 changes: 53 additions & 0 deletions src/components/items/ItemInfo/ItemInfo.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
@import '../../../styles/global.css';
@import '../../../styles/global.scss';

.item-info {
display: flex;
margin: 0 0 32px;
justify-content: space-between;
align-items: flex-start;

&__img {
width: 486px;
height: 486px;
}

&__content {
display: flex;
margin: 0 0 0 24px;
width: 690px;
height: 486px;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
}

&__title {
margin: 0 0 16px;
font-size: 24px;
font-weight: 600;
color: $gray-800;
}

&__price {
margin: 0 0 16px;
font-size: 40px;
font-weight: 600;
color: $gray-800;
}

&__content-title {
margin: 16px 0 0;
font-size: 14px;
font-weight: 500;
color: $gray-600;
}

&__desc-content {
margin: 8px 0 0;
font-size: 16px;
font-weight: 400;
line-height: 140%;
color: $gray-800;
}
}
14 changes: 13 additions & 1 deletion src/components/items/SellingItems/SellingItems.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { getProducts } from '../../../pages/api/Items';
import Item from '../Item/Item';
import PaginationBar from '../PaginationBar/PaginationBar';
import './SellingItems.css';
import { useNavigate } from 'react-router-dom';

const getPageSize = () => {
const width = window.innerWidth;
Expand All @@ -31,6 +32,7 @@ function SellingItems() {
const [totalPageNum, setTotalPageNum] = useState();
// 에러
const [fetchingError, setfetchingError] = useState(null);
const navigate = useNavigate();

const handlePageChange = (pageNumber) => {
setPage(pageNumber);
Expand All @@ -49,6 +51,12 @@ function SellingItems() {
}
};

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

navigate(`/items/${e.currentTarget.dataset.itemId}`);
};

const fetchItemList = async ({ order, page, pageSize, keyword }) => {
try {
setfetchingError(null);
Expand Down Expand Up @@ -130,7 +138,11 @@ function SellingItems() {
)}
<div className="list-selling-items">
{itemList?.map((item) => (
<Item item={item} key={`selling-item-${item.id}`} />
<Item
item={item}
key={`selling-item-${item.id}`}
handleClick={handleClickItem}
/>
))}
</div>
<div className="wrapper-pagination-bar">
Expand Down
12 changes: 11 additions & 1 deletion src/core/ui/buttons/Button/Button.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { useEffect, useRef } from 'react';

import './Button.css';
function Button({ text = '버튼', onClick = () => {}, isDisabled = false }) {
function Button({
text = '버튼',
onClick = () => {},
isDisabled = false,
iconFront,
iconBack,
customBorderRound,
}) {
const ref = useRef();

useEffect(() => {
Expand All @@ -10,7 +18,9 @@ function Button({ text = '버튼', onClick = () => {}, isDisabled = false }) {
return (
<>
<button className="btn-default" onClick={onClick} ref={ref}>
{iconFront}
{text}
{iconBack}
</button>
</>
);
Expand Down
24 changes: 24 additions & 0 deletions src/core/ui/buttons/FavoriteButton/FavoriteButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useState } from 'react';
import { ReactComponent as IconHeart } from '../../../../assets/images/icons/ic_heart.svg';
import styles from './FavoriteButton.module.scss';

function FavoriteButton({ initCount = 0 }) {
const [count, setCount] = useState(initCount);

const handleClick = () => {
setCount(count + 1);
};

return (
<>
<button className={styles.btn} onClick={handleClick}>
<div className={styles.btn__wrapper}>
<IconHeart />
<p className={styles.btn__count}>{count}</p>
</div>
</button>
</>
);
}

export default FavoriteButton;
20 changes: 20 additions & 0 deletions src/core/ui/buttons/FavoriteButton/FavoriteButton.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@import '../../../../styles/global.scss';

.btn {
border: 1px solid $gray-200;
border-radius: 35px;

&__wrapper {
display: flex;
flex-direction: row;
align-items: center;
padding: 4px 12px;
}

&__count {
margin: 0 0 0 5px;
font-size: 16px;
font-weight: 500;
color: $gray-800;
}
}
Loading

0 comments on commit 2127560

Please sign in to comment.