아마존 E-commerce 클론 -25) Seller 정보페이지 만들기
우선 셀러의 정보를 나타내는 페이지를 만들어보자.
SellerPage.js
import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { listProducts } from '../actions/productActions'
import { detailsUser } from '../actions/userActions'
import LoadingBox from '../components/LoadingBox';
import MessageBox from '../components/MessageBox';
import Rating from '../components/Rating';
function SellerScreen(props) {
const sellerId = props.match.params.id;
const userDetails = useSelector(state => state.userDetails)
const {loading, error, user} = userDetails
const productList = useSelector(state => state.productList)
const {loading:loadingProducts,error:errorProducts,products } = productList
const dispatch = useDispatch()
useEffect(() => {
dispatch(detailsUser(sellerId))
dispatch(listProducts({seller:sellerId}))
}, [dispatch, sellerId])
return (
<div className="row top">
<div className="col-1">
{loading? <LoadingBox></LoadingBox> :
error? <MessageBox variant='danger'>{error}</MessageBox> :
(
<ul className="card card-body">
<li>
<div className="row start">
<div>
<img src={user.seller.logo} alt={user.seller.name} />
</div>
<div>
<h1>{user.seller.name}</h1>
</div>
</div>
</li>
<li>
<Rating rating = {user.seller.rating} numReviews = {user.seller.numReviews}></Rating>
</li>
<li>
<a href={`mailto :${user.email}`}>Contact Seller</a>
</li>
<li>
{user.seller.description}
</li>
</ul>
)
}
</div>
<div className="col-3">
</div>
</div>
)
}
export default SellerScreen
여기서 detialsUser정보 가지고 올때, 오류나지 않도록 다음과 같이 수정해주자.
export const detailsUser = (userId) => async(dispatch, getState)=>{
dispatch({
type: USER_DETAILS_REQUEST,
payload:userId
})
const {userSignin:{userInfo}} = getState();
try{
const {data} = await axios.get(`/api/users/${userId}`, {
headers:{Authorization: `Bearer ${userInfo?.token}`}
})
dispatch({
type:USER_DETAILS_SUCCESS,
payload:data
})
}catch(error){
const message = error.response && error.response.data.message
? error.response.data.message
: error.message
dispatch({
type: USER_DETAILS_FAIL,
payload:message
})
}
}
App.js에 페이지 추가
import SellerScreen from './screens/SellerScreen';
<Route path="/seller/:id" component={SellerScreen} exact></Route>
product.js파일에 seller정보를 입력하도록 하자.
여기서 seller가 두번 들어간 이유는 seller(product모델안의 seller(use타입))로 한번 갔다가 다시
seller (user모델안의 셀러 )로 가서 이름정보를 가져오기 때문이다.
components>product.js
<div className="row">
<div className="price">
${product.price}
</div>
<div>
<Link to={`/seller/${product.seller._id}`}>{product.seller.seller.name}</Link>
</div>
</div>
여기서 만약 상품에 셀러 아이디가 없다면 오류가 발생하므로, 모든 상품을 다시 셀러정보를 입력해주자.
셀러아이디가 모두 입력되었으면,
productRouter에 가서 다음과 같이 셀러 이름과 로고를 셀러정보로 가져오도록 한다.
productRouter.get('/' ,expressAsyncHandler(async(req, res)=>{
const seller = req.query.seller || ''
const sellerFilter = seller? {seller} :{};
const products = await Product.find({...sellerFilter}).populate('seller', 'seller.name seller.logo');
res.send(products);
}));
클릭하면 셀러 화면으로 이동한다.
sellerScreen에서 이미지 사이즈를 줄이자.
<div>
<img className="small" src={user.seller.logo} alt={user.seller.name} />
</div>
이제 상품보여주는 sellerscreen의 col-3를 완성하자.(아랫부분은 홈스크린과 동일해서 그대로 가져온다)
<div className="col-3">
{loadingProducts? <LoadingBox></LoadingBox> :
errorProducts? <MessageBox variant='danger'>{errorProducts}</MessageBox> :
(
<>
{products.length===0 &&<MessageBox>No Product Found</MessageBox>}
<div className="row center">
{products.map(product=>(
<Product key={product._id} product = {product}/>
))}
</div>
</>
)
}
</div>
</div>
)
}
export default SellerScreen
스타일링을 하자
.row.start{
justify-content: flex-start;
}
...
.col-1{
flex:1 1 25rem;
}
.col-2{
flex:2 1 50rem;
}
.col-3{
flex:3 1 75rem;
}
프로필부분에도 스타일링하자.
<div className="p-1">
<img className="small" src={user.seller.logo} alt={user.seller.name} />
</div>
<div className="p-1">
<h1>{user.seller.name}</h1>
</div>
.p-1{
padding:1rem
}
상품 디테일 페이지에도 셀러 정보가 나타나도록 설정하자.
productScreen을 다음과 같이 추가해주자.
<div className="col-1">
<div className="card card-body">
<ul>
<li>
Seller
<h2><Link to={`/seller/${product.seller._id}`}>{product.seller.seller.name}</Link></h2>
<Rating rating = {product.seller.seller.rating} numReviews = {product.seller.seller.numReviews}></Rating>
</li>
productrouter에 가서 디테일 정보를 가지고 올때 populate해서 셀러정보를 가져오도록 하자.
productRouter.get('/:id' ,expressAsyncHandler(async(req, res)=>{
const product = await Product.findById(req.params.id).populate('seller', 'seller.name seller.logo seller.rating seller.numReviews');
if(product){
res.send(product);
}else{
res.status(404).send({message:'Product not Found'})
}
}))
여기서는 셀러의 정보가 있기 때문에 셀러의 상품만 리스트가 되게 된다.