Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[김정현] Sprint7 #223

38 changes: 38 additions & 0 deletions src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.App {
text-align: center;
}

.App-logo {
height: 40vmin;
pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}

.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}

.App-link {
color: #61dafb;
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
23 changes: 16 additions & 7 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import Root from './router/Root.jsx';
import ProductsPage from './router/ProductsPage.jsx';
import AddItemPage from './router/AddItemPage.jsx';
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Root from "./router/Root.jsx";
import ProductsPage from "./router/ProductsPage.jsx";
import AddItemPage from "./router/AddItemPage.jsx";
import ProductDetailPage, {
loader as productLoader,
} from "./router/ProductDetailPage.jsx";

const router = createBrowserRouter([
{
path: '/',
path: "/",
element: <Root />,
children: [
{
path: 'items',
path: "items",
element: <ProductsPage />,
},
{
path: 'additem',
path: "items/:productId",
id: "product-detail",
element: <ProductDetailPage />,
loader: productLoader,
},
{
path: "additem",
element: <AddItemPage />,
},
],
Expand Down
Binary file added src/assets/images/Img_inquiry_empty.png
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/Img_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.
Binary file added src/assets/images/[email protected]
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 src/assets/images/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/assets/images/heart_Icon.png
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 src/assets/images/ic_back.png
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 src/assets/images/img_default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions src/assets/images/img_default.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 src/assets/images/[email protected]
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 src/assets/images/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/components/DetailProduct/Comment/Comment.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import CommnetForm from './CommentForm';
import CommentList from './CommentList';

export default function Comment({ comment }) {
return (
<article style={{ marginBottom: '10rem' }}>
<CommnetForm />
<CommentList commentList={comment} />
</article>
);
}
39 changes: 39 additions & 0 deletions src/components/DetailProduct/Comment/CommentForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useState } from "react";
import styles from "./CommentForm.module.css";
import TextArea from "../../../ui/FormComponents/TextArea";
import Button from "../../../ui/Button/Button";

export default function CommnetForm() {
const [commentValue, setCommentValue] = useState("");

const handleChangeValue = (name = "comment", value) => {
setCommentValue(value);
};

const isActive = commentValue.trim() !== "";

return (
<>
<form className={styles.commentForm}>
<TextArea
id="comment"
name="comment"
type="text"
variant="comment"
label="문의하기"
value={commentValue}
placeholder="개인정보를 공유 및 요청하거나, 명예 훼손, 무단 광고, 불법 정보 유표시 모니터링 후 삭제될 수 있으며, 이에 대한 민형사상 책임은 게시자에게 있습니다."
changeValue={handleChangeValue}
/>
<div className={styles.commentBtn}>
<Button
isActive={!isActive}
variant={true}
type="submit"
btnName="등록"
/>
</div>
</form>
</>
);
}
7 changes: 7 additions & 0 deletions src/components/DetailProduct/Comment/CommentForm.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.commentForm {
margin: 2.4rem 0;
}
.commentBtn {
margin-top: 1.6rem;
text-align: right;
}
50 changes: 50 additions & 0 deletions src/components/DetailProduct/Comment/CommentList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Link } from 'react-router-dom';
import styles from './CommentList.module.css';
import convertTime from '../../../utils/convertTime';
import commentEmpty from '../../../assets/images/Img_inquiry_empty.png';
import backIcon from '../../../assets/images/ic_back.png';

export default function CommentList({ commentList }) {
const comment = commentList.length ? (
<ul className={styles.commentContainer}>
{commentList.map(comment => (
<li
key={`${comment.writer.nickname}-${comment.id}`}
className={styles.commentList}
>
<div className={styles.review}>{comment.content}</div>
<div className={styles.userInfo}>
<img
className={styles.userProfile}
src={comment.writer.image}
alt={`${comment.writer.nickname} 프로필`}
/>
<div className={styles.userComment}>
<div className={styles.userName}>{comment.writer.nickname}</div>
<div className={styles.commentTime}>
{convertTime(comment.updatedAt)}
</div>
</div>
</div>
</li>
))}
</ul>
) : (
<div className={styles.emptyComment}>
<img src={commentEmpty} alt="문의가 없습니다" />
<span>아직 문의가 없습니다.</span>
</div>
);

return (
<>
<div>{comment}</div>
<div className={styles.historyAction}>
<Link className={styles.historyBtn} to="/items">
목록으로 돌아가기
<img src={backIcon} alt="목록으로 돌아가기" />
</Link>
</div>
</>
);
}
65 changes: 65 additions & 0 deletions src/components/DetailProduct/Comment/CommentList.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
.commentContainer {
margin-bottom: 4rem;
}
.commentList {
margin-bottom: 2.4rem;
padding-bottom: 2.4rem;
border-bottom: 1px solid var(--color-gray200);
}
.commentList:last-child {
margin-bottom: 0;
}
.review {
margin-bottom: 2.4rem;
font-size: 1.6rem;
}
.userInfo {
display: flex;
align-items: flex-start;
gap: 8px;
}

.userProfile {
width: 40px;
height: 40px;
}
.userComment {
font-size: 1.4rem;
}

.emptyComment {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-bottom: 2.4rem;
}

.emptyComment > img {
width: 200px;
}

.emptyComment > span {
font-size: 1.6rem;
font-weight: 400;
color: var(--color-gray400);
}

.historyAction {
display: flex;
justify-content: center;
align-items: center;
}

.historyBtn {
display: flex;
align-items: center;
gap: 10px;
line-height: 2.4rem;
padding: 12px 38.5px;
border-radius: 40px;
font-size: 1.8rem;
font-weight: 600;
color: #fff;
background: var(--color-blue);
}
43 changes: 43 additions & 0 deletions src/components/DetailProduct/DetailProduct.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import heartIcon from '../../assets/images/heart_Icon.png';
import styles from './DetailProduct.module.css';
import defaultImage from '../../assets/images/[email protected]';

export default function DetailProduct({ product }) {
const productPrice = product.price && product.price.toLocaleString('kr');

const onErrorImg = e => {
e.target.src = defaultImage;
};

return (
<article className={styles.container}>
<img
className={styles.productImg}
src={product.images && product.images[0]}
alt={product.name}
onError={onErrorImg}
/>
<div className={styles.productDetails}>
<div className={styles.productHeader}>
<h2 className={styles.productName}>{product.name}</h2>
<p className={styles.productPrice}>{productPrice}원</p>
</div>
<div className={styles.productInfo}>
<h3 className={styles.productTitle}>상품 소개</h3>
<p className={styles.productDescription}>{product.description}</p>
</div>
<div className={styles.productTag}>
<h3 className={styles.tagTitle}>상품 태그</h3>
<ul className={styles.tagList}>
{product.tags &&
product.tags.map((tag, index) => <li key={index}>#{tag}</li>)}
</ul>
</div>
<button className={styles.favoriteCount}>
<img src={heartIcon} alt="좋아요" />
<span>{product.favoriteCount}</span>
</button>
</div>
</article>
);
}
Loading
Loading