ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백오피스 프로젝트 3. view Engline (ejs), 리뷰 CRUD, 프론트엔드 - 백엔드 연결
    Projects/Qwerty - 배달의민족 (team) 2023. 7. 24. 17:18

    1. 오늘 목표

    고객 리뷰 CRUD 

    프론트엔드- 백엔드 연결

     

     

    오늘은 , 고객이 로그인을 하고 해당 음식점에 대한 리뷰를 조회, 생성, 수정 및 삭제할 수 있도록 CRUD를 구현했다.

     

    // 리뷰 작성 API (POST)
    router.post('/user/store/:storeId/review', authMiddleware, async (req, res) => { //upload.single('image'),
      const { userId } = res.locals.user;
      const { storeId } = req.params;
      const { rating, content } = req.body;
      // const imageUrl = req.file.location;
    
      try {
        if (!storeId) {
          return res.status(404).json({ message: '해당 음식점이 존재하지 않습니다.' });
        }
        if (!rating || !content) {
          return res.status(400).json({ message: '입력값이 유효하지 않습니다.' });
        }
    
        await Reviews.create({ userId, storeId, rating, content }); //image: imageUrl, 
        return res.status(201).json({ message: '리뷰 작성에 성공하였습니다.' });
      } catch (error) {
        console.log(error);
        return res.status(400).json({ message: '리뷰 작성에 실패했습니다.' });
      }
    });
    // 리뷰 목록조회 API (GET)
    router.get('/user/store/:storeId/review', async (req, res) => {
      const { storeId } = req.params;
    
      try {
        if (!storeId) {
          return res.status(404).json({ message: '해당 음식점이 존재하지 않습니다.' });
        }
    
        const reviews = await Reviews.findAll({
          raw: true,
          attributes: ['reviewId', 'storeId', 'userId', 'rating', 'content', 'createdAt', 'updatedAt'],
          // include: [{model: Users, attributes:['userId']}], // 목록조회에 닉네임 추가.
          where: {storeId},
          order: [['createdAt', 'DESC']],
        });
        return res.status(200).json({ data: reviews });
      } catch {
        return res.status(400).json({ message: '리뷰 조회에 실패하였습니다.' });
      }
    });
    // 리뷰 수정 API (PUT)
    router.put('/user/store/:storeId/review/:reviewId', authMiddleware, async (req, res) => { //upload.single('image'),
      const { storeId, reviewId } = req.params;
      const { userId } = res.locals.user;
      const { rating, content } = req.body;
      // const imageUrl = req.file.location;
    
      try {
        if (!storeId) {
          return res.status(404).json({ message: '해당 음식점이 존재하지 않습니다.' });
        }
        const review = await Reviews.findOne({ where: { reviewId } });
        if (!review) {
          return res.status(404).json({ message: '리뷰가 존재하지 않습니다.' });
        } else if (review.userId !== userId) {
          return res.status(403).json({ message: '리뷰 수정 권한이 존재하지 않습니다.' });
        }
        if (!content) {
          return res.status(400).json({ message: '입력값이 유효하지 않습니다.' });
        }
    
        await Reviews.update(
          { rating, content }, //image: imageUrl,
          { where: { [Op.and]: [{ reviewId }, { userId }] } },
        );
        return res.status(200).json({ data: '리뷰 수정에 성공하였습니다.' });
      } catch {
        return res.status(400).json({ data: '댓글 수정에 실패하였습니다.' });
      }
    });

     

    // 리뷰 삭제 API (DELETE)
    router.delete('/user/store/:storeId/review/:reviewId', authMiddleware, async (req, res) => {
      const { storeId, reviewId } = req.params;
      const { userId } = res.locals.user;
    
      try {
        if (!storeId) {
          return res.status(404).json({ message: '해당 음식점이 존재하지 않습니다.' });
        }
        const review = await Reviews.findOne({ where: { reviewId } });
        if (!review) {
          return res.status(404).json({ message: '리뷰가 존재하지 않습니다.' });
        } else if (review.userId !== userId) {
          return res.status(403).json({ message: '리뷰 삭제 권한이 존재하지 않습니다.' });
        }
    
        await Reviews.destroy({ where: { [Op.and]: [{ reviewId }, { userId }] } });
        return res.status(200).json({ data: '리뷰 삭제에 성공하였습니다.' });
      } catch {
        return res.status(400).json({ data: '리뷰 삭제에 실패하였습니다.' });
      }
    });

     

    프론트엔드 HTML 파일 분리.

    --pages_ceo
    ceo.html  -> 사장님
    ceoGet.html  -> 사장님 회원목록 조회페이지
    ceoLogin.html -> 사장님 로그인 페이지
    ceoPost.html -> 사장님 메뉴등록 페이지
    ceoSignUp.html -> 사장님 회원가입 페이지
    
    
    --pages_customer
    cart.html -> 고객님 장바구니 페이지
    login.html -> 고객님 로그인 페이지
    order.html -> 고객님 주문 페이지
    register.html -> 고객님 회원가입 페이지
    review.html -> 고객님 리뷰 목록조회 페이지
    reviewDetail.html -> 고객님 리뷰 상세조회 페이지
    reviewEdit.html -> 고객님 리뷰 수정,삭제 페이지
    reviewWrite.html -> 고객님 리뷰 생성 페이지
    store.html -> 단일 가게 페이지
    storeSearch.html -> 가게 목록 페이지

     

    그리고 따로 Routes 폴더를 만들어 사장님파드와 고객님파트 렌더링주소를 달리 하고,  이를 app.js로 실행되에 하였다.

     

     

     

    const express = require('express');
    const router = express.Router();
    
    // GET
    
    // => localhost:3000/
    // 1. 사장님, 고객님 메인페이지
    router.route('/').get((req, res) => {
        return res.render('./index.html');
    });
    
    // => localhost:3000/ceo
    // 2. 사장님 페이지
    router.route('/ceo').get((req, res) => {
        return res.render('pages_ceo/ceo.html');
    });
    
    // => localhost:3000/ceoLogin
    // 3. 사장님 로그인 페이지
    router.route('/ceoLogin').get((req, res) => {
        return res.render('pages_ceo/ceoLogin.html');
    });
    
    // => localhost:3000/ceoPost
    // 4. 사장님 포스트 페이지
    router.route('/ceoPost').get((req, res) => {
        return res.render('pages_ceo/ceoPost.html');
    });
    
    // => localhost:3000/ceoSignup
    // 5. 사장님 회원가입 페이지
    router.route('/ceoSignup').get((req, res) => {
        return res.render('pages_ceo/ceoSignup.html');
    });
    
    module.exports = router;

     

    const express = require('express');
    const router = express.Router();
    
    // GET
    // => localhost:3000/storeSearch
    // 1. 고객이 가게를 검색해서 찾는 페이지. 검색창이랑 가게 이미지, 이름등이 올라와있다.
    router.route('/storeSearch').get((req, res) => {
      return res.render('./pages_customer/storeSearch.html');
    });
    
    // => localhost:3000/user/register
    // 2. 고객 회원가입 페이지
    router.route('/user/register').get((req, res) => {
      return res.render('pages_customer/register.html');
    });
    
    // => localhost:3000/cart
    // 3. 고객이 음식 메뉴를 선택한것들이 모여있는 장바구니 페이지
    router.route('/cart').get((req, res) => {
      return res.render('pages_customer/cart.html');
    });
    
    // => localhost:3000/detail
    // 4. 고객이 음식 구매전, 상세페이지. (수량선택하고 장바구니에 넣거나, 바로구매할수있다.)
    router.route('/detail').get((req, res) => {
      return res.render('pages_customer/detail.html');
    });
    
    // => localhost:3000/store
    // 5. 가게 한개의 상세 페이지, 상단에는 메뉴들이 있고, 하단에는 가게 리뷰가 달려있다.
    router.route('/store').get((req, res) => {
      return res.render('pages_customer/store.html');
    });
    
    // => localhost:3000/order
    // 6. 고객 주문 페이지 (실제 결제가 이뤄지는 곳)
    router.route('/order').get((req, res) => {
      return res.render('pages_customer/order.html');
    });
    
    // => localhost:3000/review
    // 7. 고객이 가게에 대한 리뷰 목록 페이지.
    router.route('/review').get((req, res) => {
      return res.render('pages_customer/review.html');
    });
    
    // => localhost:3000/user/login
    // 8. 고객 로그인페이지
    router.route('/user/login').get((req, res) => {
      return res.render('pages_customer/login.html');
    });
    
    // => localhost:3000/review/write
    // 9. 고객 리뷰작성
    router.route('/review/write').get((req, res) => {
      return res.render('pages_customer/reviewWrite.html');
    });
    
    module.exports = router;

    댓글

Designed by Tistory.