Skip to content

Commit

Permalink
컴포넌트 분리
Browse files Browse the repository at this point in the history
  • Loading branch information
김승석 authored and 김승석 committed Dec 8, 2024
1 parent 1eb200c commit 7ac5c0d
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 96 deletions.
43 changes: 6 additions & 37 deletions src/components/DetailBtm.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import menuIcon from "./../assets/menu_dot.svg";
import profileIcon from "./../assets/icon_profile.png";
import React, { useEffect, useState } from "react";
import axios from "axios";
import React, { useState } from "react";
import useApi from "./../hooks/useApi";
import ProfileBox from "./ProfileBox";

const DetailBtm = ({ id }) => {
const [comment, setComment] = useState([]);
const [commentMenu, setCommentMenu] = useState(null);
const [textValue, setTextValue] = useState("");

const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

const handleTextChange = (e) => {
setTextValue(e.target.value);
};
Expand All @@ -19,19 +15,7 @@ const DetailBtm = ({ id }) => {
setCommentMenu(commentMenu === id ? null : id);
};

useEffect(() => {
const fetchProduct = async () => {
try {
const response = await axios.get(`https://panda-market-api.vercel.app/products/${id}/comments?limit=10`);
setComment(response.data.list);
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
fetchProduct();
}, [id]);
const { data, loading, error } = useApi(`https://panda-market-api.vercel.app/products/${id}/comments?limit=10`);

if (loading) {
return <div>Loading...</div>;
Expand Down Expand Up @@ -59,14 +43,7 @@ const DetailBtm = ({ id }) => {
</button>
</div>
<ul className="comment_list">
{comment.map((el) => {
const dateString = el.updatedAt;
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
const formattedDate = `${year}.${month}.${day}`;

{data.list.map((el) => {
return (
<li key={el.id}>
<div className="comment_menu">
Expand All @@ -89,15 +66,7 @@ const DetailBtm = ({ id }) => {
)}
</div>
<div className="text_area">{el.content}</div>
<div className="name_area">
<div className="profile">
<img src={el.writer.image ? el.writer.image : profileIcon} alt={el.writer.nickname} onError={(e) => (e.target.src = profileIcon)} />
</div>
<div className="name">
<p>{el.writer.nickname}</p>
<div className="date">{formattedDate}</div>
</div>
</div>
<ProfileBox img={el.writer.image} name={el.writer.nickname} date={el.updatedAt} />
</li>
);
})}
Expand Down
56 changes: 12 additions & 44 deletions src/components/DetailTop.jsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,10 @@
import productImg from "./../assets/item.png";
import wishIcon from "./../assets/icon_wish.svg";
import profileIcon from "./../assets/icon_profile.png";
import axios from "axios";
import React, { useEffect, useState } from "react";
import useApi from "./../hooks/useApi";
import ProfileBox from "./ProfileBox";

const DetailTop = ({ id }) => {
const [product, setProduct] = useState(null);

const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

useEffect(() => {
const fetchProduct = async () => {
try {
const response = await axios.get(`https://panda-market-api.vercel.app/products/${id}`);
setProduct(response.data);
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
fetchProduct();
}, [id]);
const { data, loading, error } = useApi(`https://panda-market-api.vercel.app/products/${id}`);

if (loading) {
return <div>Loading...</div>;
Expand All @@ -32,52 +14,38 @@ const DetailTop = ({ id }) => {
return <div>Error: {error.message}</div>;
}

if (!product) {
if (!data) {
return null;
}

const dateString = product.createdAt;
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
const formattedDate = `${year}.${month}.${day}`;

return (
<div className="product_detail_item">
<div className="thum">
<img src={product.images && product.images[0] ? product.images[0] : productImg} alt={product.name} onError={(e) => (e.target.src = productImg)} />
<img src={data.images && data.images[0] ? data.images[0] : productImg} alt={data.name} onError={(e) => (e.target.src = productImg)} />
</div>
<div className="content">
<div className="tit">{product.name}</div>
<div className="price">{product.price.toLocaleString("ko-KR")}</div>
<div className="tit">{data.name}</div>
<div className="price">{data.price.toLocaleString("ko-KR")}</div>
<div className="info">
<p>상품 소개</p>
<div className="desc">{product.description}</div>
<div className="desc">{data.description}</div>
</div>
<div className="info">
<p>상품 태그</p>
<ul className="tag">
{product.tags.map((el) => (
{data.tags.map((el) => (
<li key={el}>#{el}</li>
))}
</ul>
</div>
<div className="profile_box">
<div className="name_area">
<div className="profile">
<img src={profileIcon} alt="" />
</div>
<div className="name">
<p>{product.ownerNickname}</p>
<div className="date">{formattedDate}</div>
</div>
</div>
<ProfileBox name={data.ownerNickname} date={data.createdAt} />

<button className="btn_reset wish_area">
<div className="icon">
<img src={wishIcon} alt="" />
</div>
<div className="numb">{product.favoriteCount}</div>
<div className="numb">{data.favoriteCount}</div>
</button>
</div>
</div>
Expand Down
7 changes: 7 additions & 0 deletions src/components/ProfileBox.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.name_area {display : flex; align-items: center; margin-top: 24px;}
.name_area .profile {width: 40px; height: 40px; border-radius: 50px; overflow: hidden;}
.name_area .profile img {width: 100%; height: 100%; object-fit: cover;}
.name_area .name {margin-left: 16px;}
.name_area .name > p {font-size: 1.4rem; font-weight: 500; line-height: 1.7142; cursor: pointer;}
.name_area .name > p:hover {text-decoration: underline;}
.name_area .name > .date {color: #9CA3AF; font-size: 1.4rem; font-weight: 400; line-height: 1.7142;}
21 changes: 21 additions & 0 deletions src/components/ProfileBox.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import profileIcon from "./../assets/icon_profile.png";
import useDate from "./../hooks/useDate";
import "./ProfileBox.css";

const ProfileBox = ({ img, name, date }) => {
const formattedDate = useDate(date);

return (
<div className="name_area">
<div className="profile">
<img src={img ? img : profileIcon} alt={name} onError={(e) => (e.target.src = profileIcon)} />
</div>
<div className="name">
<p>{name}</p>
<div className="date">{formattedDate}</div>
</div>
</div>
);
};

export default ProfileBox;
25 changes: 25 additions & 0 deletions src/hooks/useApi.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { useEffect, useState } from "react";
import axios from "axios";
const useApi = (url) => {
const [data, setData] = useState(null);

const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchProduct = async () => {
try {
const response = await axios.get(url);
setData(response.data);
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
fetchProduct();
}, [url]);

return { data, loading, error };
};

export default useApi;
11 changes: 11 additions & 0 deletions src/hooks/useDate.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const useDate = (dateSet) => {
const dateString = dateSet;
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
const formattedDate = `${year}.${month}.${day}`;

return formattedDate;
};
export default useDate;
21 changes: 6 additions & 15 deletions src/page/ProductDetailPage.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,11 @@
.product_detail_item .content .info > p {margin-bottom: 16px; font-size: 1.6rem; font-weight: 600; line-height: 1.625;}
.product_detail_item .content .info > .desc {color: #4B5563; font-size: 1.6rem; line-height: 1.625;}
.product_detail_item .content .info > .tag {display : flex; flex-wrap: wrap; gap:8px; }
.product_detail_item .content .info > .tag > li {padding: 6px 16px; background-color: #F3F4F6; border-radius: 50px; font-size: 1.6rem; font-weight: 400; line-height: 1.625; }
.product_detail_item .content .info > .tag > li {padding: 6px 16px; background-color: #F3F4F6; border-radius: 50px; font-size: 1.6rem; font-weight: 400; line-height: 1.625; transition: all 0.2s; cursor: pointer;}
.product_detail_item .content .info > .tag > li:hover {box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.15);}
.product_detail_item .content .profile_box {display : flex; align-items: center; margin-top: auto; }
.product_detail_item .content .profile_box .name_area {display : flex; align-items: center;}
.product_detail_item .content .profile_box .name_area .profile {width: 40px; height: 40px; border-radius: 50px; overflow: hidden;}
.product_detail_item .content .profile_box .name_area .profile img {width: 100%; height: 100%; object-fit: cover;}
.product_detail_item .content .profile_box .name_area .name {margin-left: 16px;}
.product_detail_item .content .profile_box .name_area .name > p {font-size: 1.4rem; font-weight: 500; line-height: 1.7142;}
.product_detail_item .content .profile_box .name_area .name > .date {color: #9CA3AF; font-size: 1.4rem; font-weight: 400; line-height: 1.7142;}
.product_detail_item .content .profile_box .wish_area {position: relative; margin-left: auto; display : flex; align-items: center; padding: 4px 12px; border: 1px solid #E5E7EB; border-radius: 35px; }
.product_detail_item .content .profile_box .wish_area {position: relative; margin-left: auto; display : flex; align-items: center; padding: 4px 12px; border: 1px solid #E5E7EB; border-radius: 35px; transition: all 0.2s;}
.product_detail_item .content .profile_box .wish_area:hover {box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.15);}
.product_detail_item .content .profile_box .wish_area::before {content: ''; width: 1px; height: 34px; background-color: #E5E7EB; position: absolute; left: -24px; top: 50%; transform: translateY(-50%);}
.product_detail_item .content .profile_box .wish_area .icon img {height: 24px;}
.product_detail_item .content .profile_box .wish_area .numb {margin-left: 4px; color: #6B7280; font-size: 1.6rem; font-weight: 500; line-height: 1.625;}
Expand All @@ -38,13 +34,8 @@
.product_detail_comment .comment_list > li .comment_menu > ul > li {}
.product_detail_comment .comment_list > li .comment_menu > ul > li > button {width: 140px; height: 46px; text-align: center; color: #6B7280; font-size: 1.6rem; transition: all 0.2s;}
.product_detail_comment .comment_list > li .comment_menu > ul > li > button:hover {background: #f3f4f6;}
.product_detail_comment .comment_list > li .text_area {font-size: 1.4rem; font-weight: 400; line-height: 1.7142;}
.product_detail_comment .comment_list > li .name_area {display : flex; align-items: center; margin-top: 24px;}
.product_detail_comment .comment_list > li .name_area .profile {width: 40px; height: 40px; border-radius: 50px; overflow: hidden;}
.product_detail_comment .comment_list > li .name_area .profile img {width: 100%; height: 100%; object-fit: cover;}
.product_detail_comment .comment_list > li .name_area .name {margin-left: 16px;}
.product_detail_comment .comment_list > li .name_area .name > p {font-size: 1.4rem; font-weight: 500; line-height: 1.7142;}
.product_detail_comment .comment_list > li .name_area .name > .date {color: #9CA3AF; font-size: 1.4rem; font-weight: 400; line-height: 1.7142;}
.product_detail_comment .comment_list > li .text_area {margin-bottom: 24px; font-size: 1.4rem; font-weight: 400; line-height: 1.7142;}

.detail_btn {margin-top: 64px; display : flex; justify-content: center;}
.detail_btn .btn_blue {display : flex; align-items: center; justify-content: center;}
.detail_btn .btn_blue img {margin-left: 8px;}

0 comments on commit 7ac5c0d

Please sign in to comment.