Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added favicon.ico
Binary file not shown.
30 changes: 30 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>투두 앱</title>
<link rel="stylesheet" href="style.css" />
<link rel="icon" href="/favicon.ico">
</head>
<body>
<h1 id="title"">To do list</h1>

<!-- 날짜별 조회 및 추가 날짜도 같이 사용 -->
<section id="get-by-date">
<label for="filterDate">날짜: </label>
<input type="date" id="selectedDateInput" />
</section>

<!-- 투두 입력 영역 -->
<section id="inputDiv">
<input type="text" id="todoInput" placeholder="할 일을 입력하세요." />
<button id="addBtn">추가</button>
<span id="countDisplay"></span>
</section>

<!-- 투두 리스트 영역 -->
<ul id="todoList"></ul>

<script src="script.js"></script>
</body>
</html>
127 changes: 127 additions & 0 deletions script.js
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체보기를 통해서 모든 할 일들을 조회할 수 있는 점은 좋은 듯합니다. 하지만, 전체보기 후에 오늘 날짜를 보려면, 날짜 캘린더 들어가서 클릭 후, 날짜를 클릭해야한다는 점에서 사용자 ux측면에서 불편한듯합니다ㅠ

Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
document.addEventListener("DOMContentLoaded", () => {
const todoInput = document.getElementById("todoInput");
const addBtn = document.getElementById("addBtn");
const todoList = document.getElementById("todoList");
const selectedDateInput = document.getElementById("selectedDateInput");
const countDisplay = document.getElementById("countDisplay");
const title = document.getElementById("title"); // h1 선택

//데이터 로드 & 초기화
let todos = JSON.parse(localStorage.getItem("todos")) || [];

// 날짜 입력 기본값: 오늘
selectedDateInput.value = getToday();

// 초기 렌더링
renderTodos(todos);

/*투두 추가기능*/
addBtn.addEventListener("click", () => {
const text = todoInput.value.trim();
const date = selectedDateInput.value;

if (text === "" || date === "") {
alert("할 일과 날짜를 입력하세요!");
return;
}

const todo = {
id: Date.now(),
text,
date,
completed: false, // 완료 여부 추가
};

todos.push(todo);
saveTodos();
filterByDate(date);

todoInput.value = "";
selectedDateInput.value = date; // 날짜 유지
});

/* 날짜별 조회 기능 */
selectedDateInput.addEventListener("change", () => {
filterByDate(selectedDateInput.value);
});

function filterByDate(date) {
if (!date) return;

const filtered = todos.filter((t) => t.date === date);
renderTodos(filtered);
countDisplay.textContent = `${filtered.length}개`;
}

/* 제목 클릭시 오늘 날짜로 조회 기능 */
title.addEventListener("click", () => {
selectedDateInput.value = getToday(); // 날짜 오늘로 초기화
filterByDate(selectedDateInput.value); // 조회 버튼 없이 바로 조회
});

/* 투두 렌더링 */
function renderTodos(list) {
todoList.innerHTML = "";

if (!list || list.length === 0) {
const empty = document.createElement("li");
empty.textContent = "표시할 할 일이 없습니다.";
empty.style.listStyle = "none";
todoList.appendChild(empty);
return;
}

list.forEach((todo) => {
const li = document.createElement("li");
li.dataset.id = todo.id;

// 투두 완료 체크박스
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.checked = todo.completed;
checkbox.addEventListener("change", () => {
todo.completed = checkbox.checked;
saveTodos();
renderTodos(list); // 상태 업데이트 후 다시 렌더링
});

// 할 일 텍스트
const span = document.createElement("span");
span.textContent = todo.text;
if (todo.completed) {
span.style.textDecoration = "line-through"; // 완료시 취소선
span.style.color = "gray";
}

//삭제 버튼
const delBtn = document.createElement("button");
delBtn.textContent = "삭제";
delBtn.classList.add("deleteBtn");
delBtn.addEventListener("click", () => {
todos = todos.filter((t) => t.id !== todo.id);
saveTodos();
renderTodos(todos);
});

// li에 요소 추가
li.appendChild(checkbox);
li.appendChild(span);
li.appendChild(delBtn);
todoList.appendChild(li);
});
}

/* 로컬 스토리지 저장 */
function saveTodos() {
localStorage.setItem("todos", JSON.stringify(todos));
}
});

/* 오늘 날짜 반환 */
function getToday() {
const today = new Date();
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, "0");
const day = String(today.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
}
93 changes: 93 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
@import url("https://cdn.jsdelivr.net/npm/pretendard/dist/web/static/pretendard.css");
body {
font-family: "Pretendard", "Noto Sans KR", sans-serif;
background-color: #f5f6fa;
margin: 0;
padding: 40px;
/*todo list들이 세로로 배열되도록*/
display: flex;
flex-direction: column;
align-items: center;
}

#title {
color: #636161;
font-size: 28px;
margin-bottom: 20px;
cursor: pointer;
}
#title:hover {
color: purple;
}
#inputDiv {
width: 320px;
}

#todoInput {
padding: 7px 10px;
font-size: 16px;
border: 1px solid #ddd;
border-radius: 8px;
}

#todoInput:focus {
border-color: #4a90e2;
}

#addBtn {
margin-left: 4px;
padding: 5px 10px;
font-size: 16px;
background-color: #4a90e2;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
}

#addBtn:hover {
background-color: #357abd;
}
#countDisplay {
width: 30px;
margin-left: 10px;
font-size: large;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지금 inputDiv가 countDisplay div까지 포함되어 있는 상태라,
할 일 수가 0이거나 전체 보기를 누르면, 중앙 정렬이 안되는 거 같습니다!

Image

이 부분을 수정하려면

#countDisplay.hidden {
  display: none;
}

위 코드를 추가하시고,
할 일 갯수가 0이 되면 해당 클래스가 추가되도록, js에서도 수정해보시는 것도 좋을 것 같습니다!

/* 리스트 */
#todoList {
margin-top: 20px;
padding: 0;
}

#todoList li {
width: 320px;
display: flex;
justify-content: space-between;
align-items: center;
background: white;
margin: 6px 0;
padding: 12px 16px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
font-size: 16px;
color: #444;
}

/* 삭제 버튼 */
.deleteBtn {
background-color: transparent;
color: #e74c3c;
border: none;
font-size: 14px;
cursor: pointer;
width: 40px;
flex-shrink: 0;
}

.deleteBtn:hover {
color: #c0392b;
}

#get-by-date {
margin-bottom: 50px;
}