데브코스 23일차 ( 24.11.13 수 ) 팀플1

워니·2024년 11월 13일
0

Programmers Front-end

목록 보기
23/27

< 1차 팀 프로젝트 - 노션 클로닝 >

< 작업 내용 >

  • delete icon 호버 시 마우스 커서 pointer로 변경
  • delete icon 호버 시 아이콘 색상 변경
  • delete icon 클릭 시 삭제 여부 묻는 모달 추가
  • 확인 창에서 삭제 클릭 시 "삭제되었습니다" 모달 추가
  • 각 모달 스타일 지정
<!-- index.html -->

<!-- 삭제 여부 확인 모달창 추가 -->
<div id="deleteModal" class="modal">
   <div class="modal-content">
        <p>정말로 삭제하시겠습니까?</p>
        <button id="confirmDelete" class="modal-btn confirm">확인</button>
        <button id="cancelDelete" class="modal-btn cancel">취소</button>
   </div>
</div>
<!-- 삭제 완료 확인 모달창 추가 -->
<div id="deleteAlert" class="alert-modal">
   <div class="alert-modal-content">
        <p>삭제되었습니다.</p>
        <button id="closeAlert" class="alert-close-btn">닫기</button>
   </div>
</div>

// style.css

// 호버 마우스 커서 및 아이콘 색상 변경
.icon__delete:hover {
  cursor: pointer; /* 포인터 추가 */
  filter: invert(16%) sepia(89%) saturate(6054%) hue-rotate(358deg)
    brightness(97%) contrast(113%); 
  /* 송원 추가 : 휴지통 아이콘에 마우스 올렸을 때 색상 변경 */
}

// `삭제 여부` 모달 배경 style 지정
.modal {
  display: none;
  position: fixed;
  z-index: 1000;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5); // 불투명 어둡게
}
// `삭제 여부` 모달 컨텐츠 style 지정
.modal-content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  // 화면 중앙에 위치시키기
  background-color: white;
  padding: 20px;
  border-radius: 8px; // 모서리 라운드
  text-align: center; // 텍스트 중앙 배열
  width: 300px;
}
// `삭제 여부` 모달 버튼 style 지정
.modal-btn {
  margin: 10px;
  padding: 10px 20px;
  border: none;
  border-radius: 5px; // 모서리 라운드
  cursor: pointer;
}
// 확인 버튼 style 지정
.confirm {
  background-color: #ff4d4d;
  color: white;
}
// 취소 버튼 style 지정
.cancel {
  background-color: #ccc;
  color: black;
}
// `취소 확인 모달` 배경 style 지정
.alert-modal {
  display: none;
  position: fixed;
  z-index: 1000;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
}
// `취소 확인 모달` 콘텐츠 style 지정
.alert-modal-content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  text-align: center;
  width: 300px;
}
// `취소 확인 모달` 닫기 버튼 style 지정
.alert-close-btn {
  margin: 10px;
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  background-color: #ccc;
  color: black;
}

// editor.js
import { fetchDeleteDocument, navigateTo } from "./utils.js";
// fetchDeleteDocument : Delete API 요청
// navigateTo : id값이 담긴 history

// 휴지통 버튼 들고오기
const deleteButton = document.getElementById("icon__delete");
// 삭제 여부 모달 들고오기
const deleteModal = document.getElementById("deleteModal");
// `삭제 여부 모달` 삭제 버튼 들고오기
const confirmDeleteButton = document.getElementById("confirmDelete");
// `삭제 여부 모달` 취소 버튼 들고오기
const cancelDeleteButton = document.getElementById("cancelDelete");
// `삭제 완료 확인` 모달 들고오기
const deleteAlert = document.getElementById("deleteAlert");
// `삭제 완료 확인` 닫기 버튼 들고오기
const closeAlertButton = document.getElementById("closeAlert");

// 휴지통 버튼 클릭 시 `삭제 여부 확인` 커스텀 모달 열기
deleteButton.addEventListener("click", function (e) {
  e.preventDefault();
  // history에 저장된 값이 없으면 나가기
  if (!history.state) return;
  // 있으면 `삭제 여부 확인` 모달 열기
  deleteModal.style.display = "block";
});

// `삭제 여부 확인` 모달의 "확인" 버튼 클릭 시 삭제 진행
confirmDeleteButton.addEventListener("click", async function () {
  // history에 저장된 id값 가져오기
  const docId = history.state.id;
  // id값 delete API 요청 보내기
  await fetchDeleteDocument(docId);

  // 속성값 표현식으로 타겟 설정
  const target = document.querySelector(`[data-id='${docId}']`);
  // 타겟의 상위 상위 요소 삭제 타겟 설정
  const deleteTarget = target.parentElement.parentElement;
  // 삭제
  deleteTarget.remove();

  deleteModal.style.display = "none"; // 삭제 후 모달 닫기
  deleteAlert.style.display = "block"; // 삭제 완료 알림 표시
});

// `삭제 여부 확인` 모달의 "취소" 버튼 클릭 시 모달 닫기
cancelDeleteButton.addEventListener("click", function () {
  deleteModal.style.display = "none";
});

// `삭제 완료 확인` 알림창의 "닫기" 버튼 클릭 시 알림창 닫기
closeAlertButton.addEventListener("click", function () {
  deleteAlert.style.display = "none";
});

// 모달 외부 클릭 시 모달 닫기
window.addEventListener("click", function (e) {
  if (e.target === deleteModal) { // 클릭 대상이 모달 배경이라면
    deleteModal.style.display = "none";
  }
});

< 작업 과정 및 오류 >

- hover 시 휴지통 아이콘 색상 변경 및 마우스 커서 pointer로 변경
  -> error) 아이콘은 color 등으로 색상 변경이 불가
  -> solution) filter를 활용하여 색상 변경
  
- 휴지통 아이콘 선택하면 현재 페이지 삭제 및 목록에서 삭제
  -> error) 페이지 삭제는 쉽게 해결했지만, 사이드바에서 제거 안 됨
  -> solution) 속성값 표현식 사용하여 history에 저장된 id값을 불러오고
               해당값으로 타겟 설정하여 삭제 함

// router.js
// 기본 페이지 휴지통 삭제
document.addEventListener("DOMContentLoaded", function () {
  // 페이지 로드 시 기본 페이지인지 확인하고, 아이콘 상태 설정
  toggleTrashIcon(window.location.pathname); // 현재 경로를 기준으로 아이콘 상태 설정
});

document.body.addEventListener("click", function (e) {
  // 링크 클릭 시 페이지 이동 후 아이콘 상태 갱신
  if (e.target.tagName === "A") {
    const pathname = new URL(e.target.href).pathname; // 링크의 경로 가져오기
    toggleTrashIcon(pathname); // 경로에 맞춰 아이콘 상태 갱신
  }
});

// 기본 페이지인지 확인하고 아이콘을 숨기거나 보이게 처리하는 함수
function toggleTrashIcon(pathname) {
  const iconDelete = document.getElementById("icon__delete");

  if (!iconDelete) {
    console.error("휴지통 아이콘을 찾을 수 없습니다.");
    return;
  }

  // 경로가 기본 페이지('/')일 경우 아이콘 숨기기
  if (pathname === "/") {
    iconDelete.classList.add("hidden"); // 기본 페이지에서 아이콘 숨기기
  } else {
    iconDelete.classList.remove("hidden"); // 기본 페이지가 아니면 아이콘 보이기
  }
}

< 작업 내용 >

  • 기본페이지에서만 휴지통 아이콘 사라지게 하기
<!-- index.html -->
      <button id="open-sidebar-btn" class="open-btn hidden">
        <img src="./assets/sidebar-open.svg" alt="메뉴 버튼" />
      </button>

// style.css

.icon__delete {
  display: inline-block;
}

.icon__delete.hidden {
  display: none; /* 아이콘 숨기기 */
}

// router.js
const render = async (docId = "", target = "all") => {
  const pathname = window.location.pathname;
  toggleTrashIcon(pathname);
}
// 기본 페이지인지 확인하고 아이콘을 숨기거나 보이게 처리하는 함수
function toggleTrashIcon(pathname) {
  const iconDelete = document.getElementById("icon__delete");

  if (!iconDelete) {
    console.error("휴지통 아이콘을 찾을 수 없습니다.");
    return;
  }

  // 경로가 기본 페이지('/')일 경우 아이콘 숨기기
  if (pathname === "/") {
    iconDelete.classList.add("hidden"); // 기본 페이지에서 아이콘 숨기기
  } else {
    iconDelete.classList.remove("hidden"); // 기본 페이지가 아니면 아이콘 보이기
  }
}

< 작업 과정 및 오류 >

- 기본 페이지에서 휴지통 사라지게 하기
  - 기본 페이지 경로("/")를 받아와서 동일하면 보이게,
    그렇지 않으면 사라지게 하려고 함
  -> error) 기본 페이지에서는 사라지는 것이 성공했지만, 
            다른 페이지도 사라짐
  -> solution) list를 click 했을 때 경로를 받아오게 해서,
               기본페이지인지 아닌지 확인 후 display 값 변경
  -> error) 첫 기본 페이지에서 여전히 아이콘 활성화
  -> solution) click을 안해도 기본 페이지라면 사라지게 설정 추가
  -> error) 페이지를 삭제 후 기본 페이지로 이동되게끔 기본 설정이 되어있음
            이때, 다시 아이콘이 활성화 됨
  -> solution) 용재님께서 만들어놓으신 render를 통해
               1) 현재 페이지에 대한 경로 값 받아오게 하고
               2) click 이벤트 관련 코드 삭제
               3) 받아온 경로 값으로 기본페이지 확인

< 배운 점 / 느낀 점 >

  • 모달을 커스텀해서 사용하면 다양한 확인창을 사용할 수 있다.
  • 모달 사용 시 모달창이 아닌 외부를 클릭해도 작동하게끔 설정하는 것도
    사용자 입장에서 좋은 설정인 듯
  • 아직 아이디 값을 가져오는 것에 대한 이해는 많이 부족하다.
  • 복잡한 구조나 사용해보지 못한 함수 및 매서드 등을 활용하기엔
    아직 무리가 있다.
profile
첫 시작!

0개의 댓글