ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • MovieApp 만들기) 5.Favorite 페이지 만들기
    NODE.JS 2021. 4. 27. 23:05

     

    좋아하는 영화 목록을 나타내는 Favorite page를 만들기 위해서는 

    1. favorite page template을 만들고 

    2. mongoDB에서 favorite 된 목록을 가져오고

    3. 가져온 기능을 화면에 나타내주고, 

    4. remove 기능을 추가하는 순서로 진행한다. 

     

     

     

     

    client->views->FavoritePage->FavoritePage.js파일을 만들어준다. 

     

    App.js 파일에 가서 화면을 볼 수 있게 페이지를 추가해준다. 여기서 favorite의 루트는 로그인 한 사람만 볼 수 있도록 true 로 해준다. 

    import React, { Suspense } from 'react';
    import { Route, Switch } from "react-router-dom";
    import Auth from "../hoc/auth";
    // pages for this product
    import LandingPage from "./views/LandingPage/LandingPage.js";
    import LoginPage from "./views/LoginPage/LoginPage.js";
    import RegisterPage from "./views/RegisterPage/RegisterPage.js";
    import NavBar from "./views/NavBar/NavBar";
    import Footer from "./views/Footer/Footer";
    import MovieDetail from "./views/MovieDetail/MovieDetail";
    import FavoritePage from "./views/FavoritePage/FavoritePage";
    
    //null   Anyone Can go inside
    //true   only logged in user can go inside
    //false  logged in user can't go inside
    
    function App() {
      return (
        <Suspense fallback={(<div>Loading...</div>)}>
          <NavBar />
          <div style={{ paddingTop: '69px', minHeight: 'calc(100vh - 80px)' }}>
            <Switch>
              <Route exact path="/" component={Auth(LandingPage, null)} />
              <Route exact path="/login" component={Auth(LoginPage, false)} />
              <Route exact path="/register" component={Auth(RegisterPage, false)} />
              <Route exact path="/movie/:movieId" component={Auth(MovieDetail, null)} /> 
              <Route exact path="/favorite" component={Auth(FavoritePage, true)} /> 
            </Switch>
          </div>
          <Footer />
        </Suspense>
      );
    }
    
    export default App;
    

     

    그다음 navbar에 favorite 메뉴를 추가해준다. 

    navbar->sections->leftmenu.js를 수정한다. 

    import React from 'react';
    import { Menu } from 'antd';
    const SubMenu = Menu.SubMenu;
    const MenuItemGroup = Menu.ItemGroup;
    
    function LeftMenu(props) {
      return (
        <Menu mode={props.mode}>
        <Menu.Item key="mail">
          <a href="/">Home</a>
        </Menu.Item>
        <Menu.Item key="favorite">
          <a href="/favorite">Favorite</a>
        </Menu.Item>
        
      </Menu>
      )
    }
    
    export default LeftMenu

     

    favoritePage.js 파일은 다음과 같이 수정해서 전체적인 구조를  만들어 준다.

    import React from 'react'
    
    function FavoritePage() {
        return (
            <div style={{width:'85%', margin:'3rem auto'}}>
                <h2>Favorite Movies</h2>
                <hr />
    
                <table>
                    <thead>
                        <tr>
                            <th>Movie Title</th>
                            <th>Movie RunTime</th>
                            <td>Remove from favorites</td>
                        </tr> 
                    </thead>
                    <tbody>
                        
                    </tbody>
                </table>
                        
                        
                        
                        
                        
            </div>
        )
    }
    
    export default FavoritePage
    

     

     

    그다음 favoritePage 폴더에 favorite.css 파일을 추가해서 디자인해준다. 

     

    table{
        font-family: Arial, Helvetica, sans-serif;
        border-collapse: collapse;
        width: 100%;
    }
    
    td,th {
        border: 1px solid #dddddd;
        text-align: left;
        padding: 8px;
    }
    
    tr:nth-child(even) {
        background-color: #dddddd;
    }

     

     

    css파일을 favoritePage.js에 import 해준다. 

    import './favorite.css';
    

     

    다음엔 mongoDB에서 영화정보를 가져오자. 

    favoritePage.js파일에 다음과 같은 코드를 추가한다. 

    function FavoritePage() {
    
    
        useEffect(() => {
            Axios.post('api/favorite/getFavoritedMovie',{userFrom:localStorage.getItem('userId')})//내가 누구인지를 백엔드에 같이 보내줘서 정보 가져오도록 한다. 
            .then(response =>{
                if(response.data.success){
                    
                }else{
                    alert('영화 정보를 가져오는데 실패했습니다. ')
                }
            })
        }, [])

     

     

    다음으로 route폴더의 favorite.js 파일로 가서 정보를 가져와서 프론트에 보내는 코드를 추가한다. 

    //좋아하는 영화정보 가져오기 
    router.post('/getFavoritedMovie',  (req, res) =>{
        
    
        Favorite.find({'userFrom':req.body.userFrom})
            .exec((err, favorites)=>{
                if(err)return res.status(400).send(err)
                return res.status(200).json({success:true, favorites})//좋아하는 영화들의 형식이 배열 형태로 있을 것이다. 
            })
    
        
    })

     

     

     

     

    다음으로 가져온 데이터를 화면에 출력해보자. 

    useState구문을 추가한다. 

    import Axios from 'axios';
    import React,{useEffect, useState} from 'react'
    import './favorite.css';
    
    function FavoritePage() {
        const [Favorites, setFavorites] = useState([])
    
        useEffect(() => {
            Axios.post('api/favorite/getFavoritedMovie',{userFrom:localStorage.getItem('userId')})//내가 누구인지를 백엔드에 같이 보내줘서 정보 가져오도록 한다. 
            .then(response =>{
                if(response.data.success){
                    setFavorites(response.data.favorites)
                }else{
                    alert('영화 정보를 가져오는데 실패했습니다. ')
                }
            })
        }, [])
        return (
            <div style={{width:'85%', margin:'3rem auto'}}>
                <h2>Favorite Movies</h2>
                <hr />
    
                <table>
                    <thead>
                        <tr>
                            <th>Movie Title</th>
                            <th>Movie RunTime</th>
                            <td>Remove from favorites</td>
                        </tr> 
                    </thead>
                    <tbody>
                        {favorites.map((favorite,index)=>(
                            <tr key = {index}>
                                <td>{favorite.movieTitle}</td>
                                <td>{favorite.movieRunTime}</td>
                                <td><button>Remove</button></td>
    
                            </tr>
                        ))}
                    </tbody>
                </table>
                        
                        
                        
                        
                        
            </div>
        )
    }
    
    export default FavoritePage
    

     

     

    그 다음은 ant 디자인을 적용해서 영화 이름에 마우스를 가져다 대면 사진이 뜨도록 해보자. 

    Popover를 사용한다. 

    import Axios from 'axios';
    import React,{useEffect, useState} from 'react'
    import './favorite.css';
    import {Popover} from 'antd';
    import {IMAGE_BASE_URL} from '../../Config'
    
    //..생략
    
        const renderCards = Favorites.map((favorite,index)=>{
            
            //이미지가 있을 때는 마우스 가져다 대면 사진이 뜨도록 해보자. 
             const content = (
                <div>
                    
                    {favorite.moviePost ?
                    <img src = {`${IMAGE_BASE_URL}w500${favorite.movie.Post}`}/> : "no image"}
                    
                </div>
             )
            return <tr key = {index}>
                <Popover content={content} title={`${favorite.movieTitle}`}>
                <td>{favorite.movieTitle}</td>
                <td>{favorite.movieRunTime}</td>
                <td><button>Remove</button></td>
                </Popover>
    
            </tr>
    
    
        })
    
        return (
            <div style={{width:'85%', margin:'3rem auto'}}>
                <h2>Favorite Movies</h2>
                <hr />
    
                <table>
                    <thead>
                        <tr>
                            <th>Movie Title</th>
                            <th>Movie RunTime</th>
                            <td>Remove from favorites</td>
                        </tr> 
                    </thead>
                    <tbody>
                        {renderCards}
                    </tbody>
                </table>
                        
                        
                        
                        
                        
            </div>
        )
    }
    
    export default FavoritePage
    

     

     

    그다음은 remove버튼을 활성화 해보자. 

    이번에는 이전의 버튼과 달리 파라미터가 있는 함수를 실행할 것이다. (onClick={()=>함수명(파라미터)}의 형식)

    import Axios from 'axios';
    import React,{useEffect, useState} from 'react'
    import './favorite.css';
    import {Popover} from 'antd';
    import {IMAGE_BASE_URL} from '../../Config'
    import { response } from 'express';
    
    function FavoritePage() {
        const [Favorites, setFavorites] = useState([])
    
        useEffect(() => {
            Axios.post('api/favorite/getFavoritedMovie',{userFrom:localStorage.getItem('userId')})//내가 누구인지를 백엔드에 같이 보내줘서 정보 가져오도록 한다. 
            .then(response =>{
                if(response.data.success){
                    setFavorites(response.data.favorites)
                }else{
                    alert('영화 정보를 가져오는데 실패했습니다. ')
                }
            })
        }, [])
    
        const onClickDelete = (movieId, userFrom) =>{
    
            const variables = {
                movieId, 
                userFrom
            }
    
            Axios.post('/api/favorite/removeFroemFavorite', variables)
            .then(response=>{
                if(response.data.success){
                    
                } else{
                    alert('리스트에서 지우는데 실패했습니다.')
                }
            })
    
        }
    
        const renderCards = Favorites.map((favorite,index)=>{
            
            //이미지가 있을 때는 마우스 가져다 대면 사진이 뜨도록 해보자. 
             const content = (
                <div>
                    
                    {favorite.moviePost ?
                    <img src = {`${IMAGE_BASE_URL}w500${favorite.movie.Post}`}/> : "no image"}
                    
                </div>
             )
            return <tr key = {index}>
                <Popover content={content} title={`${favorite.movieTitle}`}>
                <td>{favorite.movieTitle}</td>
                <td>{favorite.movieRunTime}</td>
                <td><button onClick={()=>onClickDelete(favorite.movieId, favorite.userFrom)}>Remove</button></td>
                </Popover>
    
            </tr>
    
    
        })
    
        return (
            <div style={{width:'85%', margin:'3rem auto'}}>
                <h2>Favorite Movies</h2>
                <hr />
    
                <table>
                    <thead>
                        <tr>
                            <th>Movie Title</th>
                            <th>Movie RunTime</th>
                            <td>Remove from favorites</td>
                        </tr> 
                    </thead>
                    <tbody>
                        {renderCards}
                    </tbody>
                </table>
                        
                        
                        
                        
                        
            </div>
        )
    }
    
    export default FavoritePage
    

     

     

    서버 쪽으로 넘어가서 실행해보자. route의 favorite.js에 다음과 같은 내용을 추가해준다. 

    router.post('/removeFromFavorite',  (req, res) =>{
        
    
        Favorite.findOneAndDelete({movieId: req.body.movieId, userFrom: req.body.userFrom})
        .exec((err, result)=>{
            if(err)return res.status(400).send(err)
            return res.status(200).json({success:true})
    
        })
        
    })

     

     

    다시 프론트에서 결과를 보여주기 위해서는 1. 리프레시 해서 새로운 목록을 받아오는 방법과 2, 하나를 뺀 결과값을 출력하는 것이 있는데 

    우리는 리프레시 해서 새롭게 보여주는 방식을 사용한다. 

     

    영화 목록을 요청하는 것은 중복되므로 fetchFavoritedMovie라는 함수로 따로 빼서 재활용 한다. 

    결과적으로 favoritePage.js는 다음과 같다. 

    import Axios from 'axios';
    import React,{useEffect, useState} from 'react'
    import './favorite.css';
    import {Popover} from 'antd';
    import {IMAGE_BASE_URL} from '../../Config'
    import { response } from 'express';
    
    function FavoritePage() {
        const [Favorites, setFavorites] = useState([])
    
        useEffect(() => {
            fetchFavoritedMovie()
    
        }, [])
    
        const fetchFavoritedMovie = ()=>{
            Axios.post('api/favorite/getFavoritedMovie',{userFrom:localStorage.getItem('userId')})//내가 누구인지를 백엔드에 같이 보내줘서 정보 가져오도록 한다. 
            .then(response =>{
                if(response.data.success){
                    setFavorites(response.data.favorites)
                }else{
                    alert('영화 정보를 가져오는데 실패했습니다. ')
                }
            })
    
        }
    
        const onClickDelete = (movieId, userFrom) =>{
    
            const variables = {
                movieId, 
                userFrom
            }
    
            Axios.post('/api/favorite/removeFroemFavorite', variables)
            .then(response=>{
                if(response.data.success){
                    fetchFavoritedMovie()
                } else{
                    alert('리스트에서 지우는데 실패했습니다.')
                }
            })
    
        }
    
        const renderCards = Favorites.map((favorite,index)=>{
            
            //이미지가 있을 때는 마우스 가져다 대면 사진이 뜨도록 해보자. 
             const content = (
                <div>
                    
                    {favorite.moviePost ?
                    <img src = {`${IMAGE_BASE_URL}w500${favorite.movie.Post}`}/> : "no image"}
                    
                </div>
             )
            return <tr key = {index}>
                <Popover content={content} title={`${favorite.movieTitle}`}>
                <td>{favorite.movieTitle}</td>
                <td>{favorite.movieRunTime}</td>
                <td><button onClick={()=>onClickDelete(favorite.movieId, favorite.userFrom)}>Remove</button></td>
                </Popover>
    
            </tr>
    
    
        })
    
        return (
            <div style={{width:'85%', margin:'3rem auto'}}>
                <h2>Favorite Movies</h2>
                <hr />
    
                <table>
                    <thead>
                        <tr>
                            <th>Movie Title</th>
                            <th>Movie RunTime</th>
                            <td>Remove from favorites</td>
                        </tr> 
                    </thead>
                    <tbody>
                        {renderCards}
                    </tbody>
                </table>
                        
                        
                        
                        
                        
            </div>
        )
    }
    
    export default FavoritePage
    

    사진으로 보면,

    리무브 버튼을 누르면,
    다음과 같이 목록이 사라지는 것을 볼 수 있다. 

     

     

    이로하여 무비 앱 만들기는 완료! 

     

     

     

Designed by Tistory.