TIL/2023.6월

TIL 최종프로젝트(12) 리뷰 기능과 프론트 정리

황소탄 2023. 6. 23. 00:44

2023.06.22 목

프론트 진도가 영 나가지 않아 부팀장님의 도움을 받아 진행했습니다.

 

아침 09:00~12:00 까지는 리뷰를 fetch를 사용하여 불러오고 조회를 위해 forEach와 createElement, appendChild를 사용하여 구조를 만들고 데이터를 넣었습니다.

 

여기서 첫 번째 문제가 발생합니다.

-리뷰모델에 img를 담기 위한 필드는 생성했지만, 시리얼라이저에는 값을 받아오지 않았기에 이미지가 들어가지 않았습니다.

class EventReviewCreateSerializer(serializers.ModelSerializer):
    """
    리뷰를 생성하기 위해 사용됩니다.
    content(text)
    grade(intchoice)
    """

    class Meta:
        model = EventReview
        fields = (
            "content",
            "grade",
            "review_image", #<- 추가
        )

->시리얼라이저에 review_image를 추가하여 해결 될 줄 알았지만

 

-postman을 사용하여, 새로운 review를 작성하였지만, review는 생성되었지만, 이미지가 저장되지 않았습니다.

->먼저 이미지를 저장하는데 쓰는 pillow가 venv에 설치되었는지 확인 했습니다.

pip list

설치가 된 것을 확인하고 프로젝트 루트의 urls.py에서 이미지를 저장하기 위한 경로가 설정되었는지 확인하였습니다.

프로젝트 시작 전 이미 기본적인 세팅을 해놓고 시작했기에 이 문제도 아니였습니다

 

->이미지가 들어갈 media 폴더를 최상위 루트에 만들어 놓지 않았기에 발생한 문제였습니다.

 이미지를 등록하면, 자동적으로 생성된다 생각했는데, 그것이 아니였습니다.

 

    const reviewGradeElement = document.createElement('p');
    reviewGradeElement.id = 'grade';
    reviewGradeElement.className = 'grade';

    switch(element.grade) {
    case 1 :
    starNum="⭐️"
    break
    case 2:
    starNum="⭐️⭐️"
    break
    case 3:
    starNum="⭐️⭐️⭐️"
    break
    case 4:
    starNum="⭐️⭐️⭐️⭐️"
    break
    case 5:
    starNum="⭐️⭐️⭐️⭐️⭐️"
    break        
    }

    reviewGradeElement.textContent = "별점 : "+ starNum + " ";

별점 기능이 3점, 4점 형태로 출력되었습니다, 같은 기능을 구현하신 팀원분의 도움으로 출력을 ⭐️형태로 변경시켜 만들었습니다.

 

리뷰 조회 시, 팀장님이 만들어 놓으신 css가 적용되지 않는 문제가 발생했습니다, 팀장님의 도움으로 

setAttribute를 사용하여 id를 사용해 css를 끌어와 해결하였습니다.

    reviewCardElement.setAttribute("class","review-card");
    reviewCardElement.className = 'review-card';

사실 이미 비슷한 형식으로 사용하고 있었지만, css에서는 review_card로 명시했기에, css에서 review-card로 변경하고 

setAttribute를 사용하여 css를 적용시켰습니다.

즉 css의 id와 사용한 id가 달라서 css가 적용되지 않았고, 이것을 해결하기 위해 setAttribute를 사용하여 css를 끌어와 적용시켰지만, 사실 id가 달라서 적용이 안되었던 것이지, setAttribute를 사용할 필요가 없었던 것입니다!

 

이후 불러온 리뷰를 어떻게 출력해야하는지 몰라, 해결방법을 찾았습니다.

window.onload = function() {
  EventDetail()
  Eventreview()
}

윈도우가 로드 될 시 작동할 함수를 등록하여, 한 번에 관리하는 방법이 있어, 사용하였습니다.

 

그렇게 조회를 만들고 이후 부팀장님과 함께, 리뷰 작성, 삭제 기능을 구현했습니다.

                        <p class="review-title">댓글</p>
                        <div class="sub-content">
                            <select id="grade">
                                <option>1점</option>
                                <option>2점</option>
                                <option>3점</option>
                                <option>4점</option>
                                <option>5점</option>
                            </select>
                            <input id="in_img" type="file">
                            <img id="com_image" class="comment_img" src="">
                            <input id="com_txt" type="txt">
                            <button onClick="HandleComment()">등록</button>
                        </div>

리뷰 작성의 경우 id를 만들고 id를 사용하여, 해당하는 id에 값을 받아 patch를 사용해 post 해 주는 형식으로 구현 했습니다.

button에 onClack=함수를 사용하여 등록 버튼 사용 시 작성한 내용을 담아 post하는 형태로 작동합니다.

async function HandleComment(){
  const select_grade = document.getElementById('grade').value;
  const in_img = document.getElementById('in_img').files[0];
  const com_txt = document.getElementById('com_txt').value;

  const grade = select_grade.split('')[0]
  
  const formdata = new FormData();

  formdata.append("grade", grade)
  formdata.append("review_image", in_img)
  formdata.append("content", com_txt)

  const response = await fetch(`${backend_base_url}/events/${event_id}/review/`, {
    headers: {
        "Authorization": `Bearer ${token}`
    },
    method: 'POST',
    body: formdata
  }) 
  if (response.status == 201) {
    // 방법생각해보기
    alert("작성완료")
    window.location.reload()

  } else {
    (response.status)
  }
}

원래는 onload 시 작성한 리뷰가 보이는 것이 아닌 innerHTML 프로퍼티를 사용하여, 등록 버튼을 사용 시 최상단에 만든 리뷰를 출력시켜 주려고 했습니다.

그렇기에 해당 형태를 만들어주고, 값을 넣기위한 준비를 하였지만, 생각한 형태로 만들어지지 않아, 일단 onload 형태로 구현하게 되었습니다.

https://developer-talk.tistory.com/860

 

[JavaScript]innerHTML 프로퍼티 사용 방법

innerHTML 프로퍼티 사용 방법 이번 포스팅은 innerHTML 프로퍼티의 역할과 사용 방법을 소개합니다. innerHTML 프로퍼티란? innerHTML 프로퍼티는 HTML에 새로운 HTML 요소를 추가하거나 특정 HTML 요소 내부

developer-talk.tistory.com

 

삭제의 경우

async function HandleCommentDelete(get_review_id) {
  const response = await fetch(`${backend_base_url}/events/${event_id}/${get_review_id}`,{
    headers: {
        "Authorization": `Bearer ${token}`
    },
    method: 'DELETE'
  })
  if (response.status == 204) { 
    alert("삭제완료")
    window.location.reload()
    
  } else if(response.status == 403) {
    alert("작성하신 글이 아닙니다.")    
  }
  else if(response.status == 401) {
    alert("로그인이 필요합니다.")    
  }    
  else {
    alert("잘못된 접근입니다.")
  }
}

삭제를 위한 함수를 만들고 

    const reviewButton = document.createElement('button');
    reviewButton.id = 'deletebtn'
    reviewButton.setAttribute("onclick",`HandleCommentDelete(${get_review_id})`)
    reviewButton.textContent = "삭제하기"

삭제를 담당한 버튼을 만들어 리뷰 안에 넣어주었습니다.

css는 어렵습니다 감각도 부족합니다

 

코드를 정리했습니다.

1. console.log를 사용하여 결과를 출력하던 부분을 alert을 사용하여 사용자가 확인 할 수 있는 형태로 코드를 정리했습니다.

2. 전체적으로 url을 프로젝트 내에서 사용하는 변수를 사용해 표현해 주었습니다.

before
http://127.0.0.1:8000/evnet-detail.html?event_id=${event_id}`;

after
`${frontend_base_url}/event-detail.html?event_id=${event_id}`;

 3. 쿼리스트링을 사용하여, 프론트 url을 연결해 주었습니다.

event.html
      eventImage.addEventListener('click', function() {
        const event_id = parseInt(element.id, 10);
        window.location.href = `${frontend_base_url}/event-detail.html?event_id=${event_id}`;
      });
      
event-detail.html
  const urlParams = new URLSearchParams(window.location.search);
  event_id = urlParams.get('event_id');
  const eventDetailURL = `${frontend_base_url}/event-detail.html?event_id=${event_id}`;

event.html에서 event_id를 사용하여, 해당 event를 찾아 상세 페이지로 이동하게 동작합니다.

 

[느낀점]

어떻게 프론트를 어느정도 구현했습니다.

오늘 테스트를 하면서 몇몇 수정이 필요한 부분이 있었습니다.

  • 현재 event.html에서 event-image 부분을 클릭하여 넘어가게 만들었지만, contant-txt 부분이 있는 곳은 클릭 시 이동이 안되는 문제가 있습니다, 이를 해결하기 위한 고민이 필요해 보입니다.
  • 좋아요, 북마크를 했을 시 아이콘의 모양이 변경되어 사용자가 북마크를 했는지, 좋아요를 했는지 구분가능하게 구현이 필요합니다.
  • 현재 nav에 여유공간을 주지 않아 스크롤을 아무리 내려도, 컨텐츠가 짤려 제대로 출력되지 않는 문제가 있습니다, 해당 부분에 여유 공간을 주어 해결 할 수 있는지 확인해야 합니다.