NODE.JS

아마존 E-commerce 클론 -25) Seller 정보페이지 만들기

dodop 2021. 5. 29. 19:22

 

우선 셀러의 정보를 나타내는 페이지를 만들어보자. 

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);
}));

 

 

 

클릭하면 셀러 화면으로 이동한다. 

contact seller 누르면 셀러메일 주소로 넘어간다.

 

 

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'})
    }
}))

 

여기서 셀러이름을 누르면
셀러 상세페이지로 이동한다

여기서는 셀러의 정보가 있기 때문에 셀러의 상품만 리스트가 되게 된다.