[Node.js][TIL] BackOffice project - 음식 배달 서비스 구현 - 리뷰 API(3) 마무리

Trippy·2023년 12월 19일
0

Node.js

목록 보기
27/28
post-thumbnail

저번주 화요일 부터 시작했던 프로젝트를 하는 일주일동안 시간이 없어서 til을 몰아서 쓰고 있었다.
개발을 하면서 이건 til에 써봐야 겠다 할 만큼 구현하는데 시간 가는줄 모르고 하다 마감 하루 전날 새벽이 순식간에 지나갓었다. 발표 한 시간 전에 결국 원하는대로 구현을 성공했었다.

매번 프로젝트 할 떄마다 시간이 많이 없었다고 느끼지만 그래도 저번 프로젝트에 비해서 속도가 훨씬 빨라서 더 많은 양을 소화할 수 있었다.

이번에는 백엔드 구현 뿐만 아니라 결국 서비스를 할 수 있도록 프론트 구현과 프론트 연결 또한 했어야 하는부분에 있어서 시간이 더욱 오래 걸리고 프론트-백엔드 간의 중간지점에서의 이해도가 더욱 필요했고, 처음에는 많이 햇갈렸다.


생각해보니까 저번에 썼던 주문 CRUD를 구현하는 과정에서, 사업장에서 주문을 READ(조회)하는 과정이나 다른 여러가지 API에서 주문 TABLE을 참조해야하는 일이 많은데 대부분 Restaurant에서 필요로 참조하는 일이 많았기 때문에 간접 관계로 다른 테이블로 통해서 JOIN해야되는 상황이 API를 짜는 과정에서 내 머릿속을 더 어지럽게 만들어서 구현하는데 있어서 더 어려움이 있어서 생각 한 것이 그냥 주문 테이블에도 레스토랑id값을 foreign key로 추가하여 직접 관계로 db테이블을 수정하는 것이 더 편하다고 생각했다.

주황색부분이 추가 한 부분이다.



리뷰 Backend logic

일단 리뷰를 만들기 위해서는 사용자 입장에서는 몇 가지 조건이 필요하다.

  • 그 가게의 메뉴를 주문을 한 적이 있나?
  • 그 주문의 상태가 배달완료 상태인가?
  • 해당 주문에 대해서 이미 리뷰를 작성한 적이 있는가?

리뷰 테이블에는 별점과, 리뷰내용이 들어가게 된다.

별점은 주고 싶은 별의 개수를 직접 클릭해서 해당 값을 body에 실어 줄 것 이고
리뷰 내용은 input값을 body에 실어 보내 줄 것이다.

먼저 리뷰를 구상했던대로 구현하기 위해서 와이어프레임을 수정했다.

와이어 프레임을 구상하고 먼저 해당 가게 상세 페이지로 들어 갔을 때 주문을 한 내역을 userId값과 같은 것들끼리만 가지고 온다.

그런다음 조회 되는 주문 내역 중에서 배달완료 상태인 것과 리뷰를 작성한 적이 없는 조건을 통화 한 것들을 리뷰 탭에 나타 내준다.

선택한 orderId와 별점, 리뷰내용을 body 값에 실어서 review post api를 호출한다.


리뷰 frontend logic

다음은 프론트에서 동작하는 js 로직 구현이다

// 리뷰 불러오기
const loadReviews = async () => {
  try {
    const reviews = await axios.get(
      `/api/suragan/${restaurantId}/order/review`
    );
    console.log("reviews", reviews.data.data[0].Reviews);
    const review = reviews.data.data;

    let reviewList = ``;
    review.forEach((data) => {
      console.log(data.Reviews);
      reviewList += `
      
      <div class="review-info-grid">
                <h6>주문번호: ${data.Reviews.OrderId}</h6>
                <p class="review-stars">
                  <img src="./image/stars.png" width="80" class="review-stars-png" /><span class="td2">${data.Reviews.createdAt.slice(
                    0,
                    10
                  )}</span>
                </p>
                <p class="review-text">${data.Reviews.review}</p>
              </div>
              `;
    });
    document.querySelector(".review-set").innerHTML = reviewList;
  } catch (error) {
    console.error("Error fetching posts", error);
  }
};
loadReviews();

// 주문 내역 불러오기
const loadOrderToReview = async () => {
  try {
    const response = await axios.get(`/api/suragan/${restaurantId}/order/user`);
    const orderArr = response.data.data;
    console.log("orderArr: ", orderArr);

    let reviewList = ``;
    for (let i = 0; i < orderArr.length; i++) {
      const orderId = orderArr[i].orderId;
      const orderDetail = orderArr[i].orderDetails[0].menuName;

      const result = await axios.get(
        `/api/suragan/${restaurantId}/order/review/${orderId}`
      );
      console.log("result", result);
      if (!result.data.data) {
        reviewList += `<option value="${orderId}">주문번호: ${orderId} 메뉴: ${orderDetail}</option>`;
      }
    }
    document.querySelector("#order-review").innerHTML = reviewList;
  } catch (error) {
    console.error("Error fetching posts", error);
  }
};
loadOrderToReview();

// 리뷰 등록 버튼
document.addEventListener("DOMContentLoaded", () => {
  // 별점
  let clickedIndex = null;
  for (let i = 1; i <= 5; i++) {
    let starsClick = document.getElementById(`star-${i}`);
    starsClick.addEventListener("click", (e) => {
      e.preventDefault();

      clickedIndex = Number(starsClick.id.split("-")[1]);

      for (let j = 1; j <= 5; j++) {
        let star = document.getElementById(`star-${j}`);

        if (j <= clickedIndex) {
          star.classList.replace("fa-regular", "fa-solid");
        } else {
          star.classList.replace("fa-solid", "fa-regular");
        }
      }
    });
  }

  const reviewBtn = document.querySelector(".review-btn");
  reviewBtn.addEventListener("click", () => {
    const inputValue = document.querySelector(".review-input").value;
    if (clickedIndex && inputValue) {
      createReviewfunc();
      alert("리뷰 등록 완료!");
      window.location.reload();
    } else {
      alert("내용을 모두 입력 해야 합니다.");
    }
  });

  const createReviewfunc = async () => {
    try {
      const inputValue = document.querySelector(".review-input").value;
      const orderid = document.querySelector("#order-review").value;

      const createReview = await axios.post(
        `/api/suragan/${restaurantId}/order/review/${+orderid}`,
        {
          OrderId: +orderid,
          star: clickedIndex,
          review: inputValue,
        }
      );
    } catch (error) {
      console.error("Error fetching posts", error);
    }
  };
});
profile
감금 당하고 개발만 하고 싶어요

0개의 댓글