나만의 아고라 스테이츠 만들기

유주성·2023년 5월 9일
0
post-thumbnail

아고라 스테이츠란?

아고라 스테이츠는 코드스테이츠에서 수강생들이 질문을 하면 수강생들이 답변을 해주고, 답변이 안된 답은 강사가 답을 해주는 디스코드의 공간이다. 한번도 질문을 해본 적은 없지만, 다른 사람들이 질문 하는 것들을 보며 나라면 어떻게 해결 할까를 생각해보는 시간을 많이 가졌던 것 같다.

나만의 아고라 스테이츠 만들기

이번 과제는 이런 아고라 스테이츠를 직접 웹페이지로 구현 하는 것이다. 물론 완벽하게 똑같은 기능을 하도록 구현을 할 수는 없으나, 주어진 스텝에 맞추어 최대한 구현을 하려고 노력해보았다.

CSS

html은 이미 코트스테이츠 측에서 어느정도 기본 구조를 잡아 주었기 때문에 css와 자바스크립트를 작성하면 되었다. css는 전체적인 구조와 내가 입력하는 부분, 그리고 질문들이 저장되 출력되는 부분을 나누어 css를 작성하였다. 색 배열은 색 배열에서 참고하여 진행하였다. 하고나서 다른 동료들이 한 것을 보았는데, 구현은 그래도 내가 어느정도 잘 했는데 css적인 부분에서 내가 고민을 너무 안한게 티가 났던 것 같다. 앞으로는 더 신경써야 겠다.

/*기본적 구조 */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body {
  background-color: aliceblue;
  height: 100vh;
  width: 100vw;
}
main {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
}

기본적인 구조는 항상 비슷하게 시작하는 것 같다. 마진과 패딩을 0으로 세팅하고, flex-box를 이용해 앞으로 담길 내용을 중앙으로 이동 시켜 주었다.

/*입력*/
h1 {
  margin-top: 10px;
  font-size: 40px;
  color: #40514E;
}

.form__container { 
  background-color: #97e4da;
  padding: 10px;
  border-radius: 10px;
  color: #495e5a;
  font-size: small;
  width: 540px;
}

.form__input--name {
  display: flex;
  justify-content: space-between;
  margin-bottom: 5px;
}

#name {
  border: none;
}
.form__input--title{
  display: flex;
  justify-content: space-between;
  margin-bottom: 5px;
}
.form__textbox{
  display: flex;
  justify-content: space-between;
  margin-bottom: 5px;
}
#story {
  width:300px;
}
.buttons {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}
.form__submit,.reactivate{
  width: 250px;
  height: 25px;
}

#submit ,#reactivate_button{
  width: 250px;
  height: 25px;
  background-color: #E4F9F5;
  border: 1px solid #E4F9F5;
  border-radius: 20px;
}
#submit:active ,#reactivate_button:active{
  background-color: #00dcb4;
}

입력 부분 역시 flex-box를 이용해 구현을 하였고, 최대한 심플하게 만들기 위해 노력을 했다.

/*리스트*/
.discussion__wrapper {
  margin-top: 10px;
  background-color: #E4F9F5;
  width: 540px;
  padding: 2px;
}
li[class ='discussion__container'] {
  background-color: white;
  margin: 10px;
  display: flex;
  flex-direction: row;
  height: 100px;
  align-items: center;
  justify-content: left;
  border-radius: 20px;
}
ul {
  list-style: none;
}
.discussion__avatar--image {
  width: 48px;
  border-radius: 50%;
  display: inline-block;
  margin: 5px
}
.discussion__content{
  display: flex;
  flex-direction: column;
}
.discussion__title  > a{
  color: black;
  font-size: 15px;
}
.discussion__answered{
  margin-left:auto;
}

.pagination {
  display: flex;
  flex-direction: row;
}
.page_button {
  margin: 10px;
}

리스트 부분은 가장 적용해야 할게 많았다. 그냥 두면 위치가 엉망으로 있어서 이것 역시도 flex-box를 이용해 해결했다. 수업시간에 강사님은 justify-content: space-between을 이용해 내부를 정렬했지만, 나는 그냥 왼쪽에 있어야 할 것들은 justify-content: left를 이용해 붙히고, 오른쪽에 있어야 할 것은 margin-left:auto 를 이용해 왼쪽 마진을 최대로 주어 오른쪽으로 정렬을 했다.

자바스크립트

이번에 정말로 많은 양의 DOM코드를 사용해 봐서 약간 헷갈렸던 부분들이 많이 해소가 된 것 같다. 코드 양이 갑자기 확 늘어서 어질어질 하긴 했지만, 나름 잘 마무리 한 것 같다. 페이지네이션을 구현 하려 했으나 못한 것은 아쉽다.

// convertToDiscussion은 아고라 스테이츠 데이터를 DOM으로 바꿔줍니다.
const convertToDiscussion = (obj) => {
  const li = document.createElement("li"); // li 요소 생성
  li.className = "discussion__container"; // 클래스 이름 지정

  const avatarWrapper = document.createElement("div");
  avatarWrapper.className = "discussion__avatar--wrapper";
  const discussionContent = document.createElement("div");
  discussionContent.className = "discussion__content";
  const discussionAnswered = document.createElement("div");
  discussionAnswered.className = "discussion__answered";

  // TODO: 객체 하나에 담긴 정보를 DOM에 적절히 넣어주세요.

  const imager = document.createElement("img");
  imager.setAttribute('src', obj.avatarUrl);
  imager.setAttribute('alt', 'avatar of' + obj.id);
  imager.classList.add("discussion__avatar--image");
  avatarWrapper.append(imager);

  const d_title = document.createElement("h2");
  d_title.classList.add("discussion__title");
  const ank = document.createElement("a");
  ank.setAttribute("href", obj.url);
  ank.textContent = obj.title;
  d_title.append(ank);
  const discussion_i = document.createElement("div");
  discussion_i.classList.add("dicussion__information");
  discussion_i.textContent = obj.author + "/" + obj.createdAt;
  discussionContent.append(d_title, discussion_i);

  const ptag = document.createElement("p");
  if (obj.answer === null) {
    ptag.textContent = "☒";
  } else {
    ptag.textContent = "☑";
  }
  discussionAnswered.append(ptag);

  li.append(avatarWrapper, discussionContent, discussionAnswered);
  return li;
};

다른 자바스크립트 파일에 있는 데이터를 가져와 DOM을 이용하여 리스트로 출력하는 함수이다. 처음에 시작할 때는 엄청 막막했는데 막상 하나하나 작성해 나가니깐 금방 완성 할 수 있었다.

//데이터를 입력하여 저장하는 함수
const submitButton = document.querySelector(".form");
let dislist = [];
submitButton.addEventListener("submit" , function(event){
  event.preventDefault();
  let name = document.querySelector("#name").value;
  let title_t = document.querySelector("#title").value;
  let story = document.querySelector("#story").value;
  const new_li = {
    id: "D_kwDOHOApLM4APjJi",
    createdAt: new Date((new Date()).getTime() + (1000*60*60*9)).toISOString(),
    title: title_t,
    url: "https://github.com/codestates-seb/agora-states-fe/discussions/45",
    author: name,
    answer: null,
    bodyHTML:
      '<p dir="auto">--------------- 여기서부터 복사하세요 ---------------</p>\n<p dir="auto">운영 체제: 예) macOS</p>\n<p dir="auto">현재 어떤 챕터/연습문제/과제를 진행 중이고, 어떤 문제에 부딪혔나요?<br>\nPair 과제 / JavaScript Koans</p>\n<p dir="auto">npm install 명령어 입력 시 env: node: No such file or directory 라고 뜹니다</p>\n<p dir="auto">에러 발생하여 아래 명령어 실행 했는데도 불구하고 똑같은 에러가 발생했습니다<br>\nnpm cache clean --force</p>\n<p dir="auto">rm package-lock.json</p>\n<p dir="auto">rm -rf ./node_modules/</p>\n<p dir="auto">npm --verbose install</p>\n<p dir="auto">폴더 자체가 문제가 있다고 생각하여 github에서 다시 fork 후 진행했는데도 같은 에러가 발생했습니다<br>\n리눅스 기초 챕터 때 npm 설치해서 마지막 submit까지는 잘 됐는데 현재 짝수 생성기 폴더도 똑같이 npm install 시 no such file or directory가 발생합니다</p>\n<p dir="auto">에러가 출력된 곳에서, 이유라고 생각하는 부분을 열 줄 이내로 붙여넣기 해 주세요. (잘 모르겠으면 에러라고 생각하는 곳을 넣어주세요)</p>\n<div class="highlight highlight-source-js position-relative overflow-auto" data-snippet-clipboard-copy-content="minjun@dubi fe-sprint-javascript-koans-main % pwd \n/Users/minjun/Documents/fe_frontand_39/fe-sprint-javascript-koans-main\nminjun@dubi fe-sprint-javascript-koans-main % npm install \nenv: node: No such file or directory"><pre><span class="pl-s1">minjun</span>@<span class="pl-s1">dubi</span> <span class="pl-s1">fe</span><span class="pl-c1">-</span><span class="pl-s1">sprint</span><span class="pl-c1">-</span><span class="pl-s1">javascript</span><span class="pl-c1">-</span><span class="pl-s1">koans</span><span class="pl-c1">-</span><span class="pl-s1">main</span> <span class="pl-c1">%</span> <span class="pl-s1">pwd</span> \n<span class="pl-c1">/</span><span class="pl-v">Users</span><span class="pl-c1">/</span><span class="pl-s1">minjun</span><span class="pl-c1">/</span><span class="pl-v">Documents</span><span class="pl-c1">/</span><span class="pl-s1">fe_frontand_39</span><span class="pl-c1">/</span><span class="pl-s1">fe</span><span class="pl-c1">-</span><span class="pl-s1">sprint</span><span class="pl-c1">-</span><span class="pl-s1">javascript</span><span class="pl-c1">-</span><span class="pl-s1">koans</span><span class="pl-c1">-</span><span class="pl-s1">main</span>\n<span class="pl-s1">minjun</span><span class="pl-kos"></span>@<span class="pl-s1">dubi</span> <span class="pl-s1">fe</span><span class="pl-c1">-</span><span class="pl-s1">sprint</span><span class="pl-c1">-</span><span class="pl-s1">javascript</span><span class="pl-c1">-</span><span class="pl-s1">koans</span><span class="pl-c1">-</span><span class="pl-s1">main</span> <span class="pl-c1">%</span> <span class="pl-s1">npm</span> <span class="pl-s1">install</span> \nenv: node: <span class="pl-v">No</span> <span class="pl-s1">such</span> <span class="pl-s1">file</span> <span class="pl-s1">or</span> <span class="pl-s1">directory</span></pre></div>\n<p dir="auto">검색했던 링크가 있다면 첨부해 주세요.<br>\n<a href="https://mia-dahae.tistory.com/89" rel="nofollow">https://mia-dahae.tistory.com/89</a></p>\n<p dir="auto"><a href="https://stackoverflow.com/questions/38143558/npm-install-resulting-in-enoent-no-such-file-or-directory" rel="nofollow">https://stackoverflow.com/questions/38143558/npm-install-resulting-in-enoent-no-such-file-or-directory</a></p>\n<p dir="auto"><a href="https://velog.io/@hn04147/npm-install-%ED%95%A0-%EB%95%8C-tar-ENOENT-no-such-file-or-directory-lstat-%EC%97%90%EB%9F%AC%EB%82%A0-%EA%B2%BD%EC%9A%B0" rel="nofollow">https://velog.io/@hn04147/npm-install-%ED%95%A0-%EB%95%8C-tar-ENOENT-no-such-file-or-directory-lstat-%EC%97%90%EB%9F%AC%EB%82%A0-%EA%B2%BD%EC%9A%B0</a></p>\n<p dir="auto"><a href="https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;blogId=chandong83&amp;logNo=221064506346" rel="nofollow">https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;blogId=chandong83&amp;logNo=221064506346</a></p>\n<p dir="auto"><a href="https://webisfree.com/2021-07-15/npm-install-%EC%97%90%EB%9F%AC-%EB%B0%9C%EC%83%9D-rename-no-such-file-or-directory-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B0%80" rel="nofollow">https://webisfree.com/2021-07-15/npm-install-%EC%97%90%EB%9F%AC-%EB%B0%9C%EC%83%9D-rename-no-such-file-or-directory-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B0%80</a></p>\n<p dir="auto"><a href="https://hellowworlds.tistory.com/57" rel="nofollow">https://hellowworlds.tistory.com/57</a></p>',
    avatarUrl: 'images.png',
  }
  agoraStatesDiscussions.unshift(new_li);
  ul.insertBefore(convertToDiscussion(new_li),ul.firstChild);
  dislist.push(new_li);
  console.log(dislist);
  localStorage.setItem("discuss",JSON.stringify(dislist));
});

//로컬 스토리지 이용해 새로고침해도 데이터가 유지되도록 만들기
window.onload = function() {
  let storedD = JSON.parse(localStorage.getItem("discuss"));
  console.log(storedD);
  if(storedD){
    for(let i = 0; i < storedD.length;i++){
    agoraStatesDiscussions.unshift(storedD[i]);
    ul.insertBefore(convertToDiscussion(storedD[i]),ul.firstChild);
    }
  };
  if (storedD !== null){
    dislist = storedD;
  }
  
};

데이터를 입력하여 저장하는 함수이다. 처음에는 그냥 DOM으로 출력되게만 만들었었는데 그렇게 하면 새로고침시에 처음 페이지를 시작한 화면으로 돌아와서 로컬스토리지를 이용해 저장해 이용하였다.

//초기화
const reactivate = document.querySelector("#reactivate_button");
reactivate.addEventListener("click",function(event){
  window.localStorage.clear()
  location.reload()
});

초기화는 다른 사람들 제출물을 참고 하였는데, 너무 어려운 것들은 구현하려면 시간이 오래 걸릴 것 같았지만 이것은 금방 할 수 있을 것 같아서 만들었다. 로컬 스토리지의 값들을 삭제해주고 페이지를 새로고침하면 초기화 된다.

// agoraStatesDiscussions 배열의 모든 데이터를 화면에 렌더링하는 함수입니다.
const render = (element) => {
  for (let i = currentpage * 10; i < agoraStatesDiscussions.length; i += 1) {
    element.append(convertToDiscussion(agoraStatesDiscussions[i]));
  }
  return;
};

// ul 요소에 agoraStatesDiscussions 배열의 모든 데이터를 화면에 렌더링합니다.
const ul = document.querySelector("ul.discussions__container");
render(ul);

코드스테이츠에서 제공한 렌더링 함수이다. 나머지 부분의 코드를 짜는데 힌트가 많이 된 것 같다.

0개의 댓글