diff --git a/checkmark.svg b/checkmark.svg new file mode 100644 index 0000000..8738f16 --- /dev/null +++ b/checkmark.svg @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/index.html b/index.html index d241b1b..1ef8775 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + @@ -8,7 +8,23 @@ -
+
+
+

To Do โœ๏ธ

+
+
+
+

Today's To-Do ๐Ÿ€

+

+

โœ… : 0 ๐ŸŽ‰ : 0

+
+ + +
+
    +
    +
    + diff --git a/script.js b/script.js index 355dcc2..80b5b57 100644 --- a/script.js +++ b/script.js @@ -1 +1,143 @@ //๐Ÿ˜CEOS 20๊ธฐ ํ”„๋ก ํŠธ์—”๋“œ ํŒŒ์ดํŒ…๐Ÿ˜ + +document.addEventListener("DOMContentLoaded", function () { + const today = new Date(); // ํ˜„์žฌ ๋‚ ์งœ์™€ ์‹œ๊ฐ„์„ ๊ฐ€์ ธ์˜ค๋Š” Date ๊ฐ์ฒด + const options = { month: "long", day: "numeric", weekday: "long" }; + // ๋‚ ์งœ, ์š”์ผ ๋“ฑ ํฌ๋งท ์‹œ month์™€ weekday๋Š” ๊ธด ํ˜•์‹์œผ๋กœ (9์›”, ๋ชฉ์š”์ผ) day๋Š” ์ˆซ์ž ํ˜•์‹ (5, 25) + + const formattedDate = today.toLocaleDateString("ko-KR", options); // options ํ˜•์‹์˜ ํ•œ๊ตญ์–ด ๋‚ ์งœ + document.querySelector(".date").textContent = formattedDate; + // .Date ์š”์†Œ์˜ textcontent๋ฅผ formattedDate์œผ๋กœ ์„ค์ • + + const todoInput = document.querySelector("input"); // input ์š”์†Œ ๊ฐ€์ง€๊ณ  ์˜ค๊ธฐ + const todoBox = document.querySelector(".todoBox"); // class๊ฐ€ .todo-box์ธ ์š”์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ค๊ธฐ + const submitBtn = document.getElementById("submitBtn"); // id๊ฐ€ submitbtn์ธ ์š”์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ค๊ธฐ + const completedCountElem = document.querySelector(".completedCount"); // ์™„๋ฃŒ๋œ todo ์ˆ˜๋ฅผ ์…€ ์š”์†Œ + const totalCountElem = document.querySelector(".totalCount"); // ์ „์ฒด todo ์ˆ˜๋ฅผ ์…€ ์š”์†Œ + + let todoList = []; // ๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅ๋  todo ๋ฐฐ์—ด + + function setting() { + loadStorage(); // localStorage์— ์ €์žฅ๋œ todoList์˜ todo๋“ค ๋ถˆ๋Ÿฌ์˜ค๊ธฐ + submitBtn.addEventListener("click", function (event) { + event.preventDefault(); // input์— ๊ฐ’ ์ž…๋ ฅ ํ›„ ์ถ”๊ฐ€ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ๋„ ์ƒˆ๋กœ๊ณ ์นจ ๋˜์ง€ ์•Š๋„๋ก. + createList(); + }); + } + + function createList() { + const newTodo = todoInput.value.trim(); // ๋ฌธ์ž์—ด ์•ž ๋’ค ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•˜๋Š” trim์„ ์ด์šฉ, ์‚ฌ์šฉ์ž๊ฐ€ input์— ์ž…๋ ฅํ•œ todo๋ฅผ ์ €์žฅ + if (newTodo === ""){ + alert('์˜ค๋Š˜์˜ ํ•  ์ผ์„ ์ ์–ด์ฃผ์„ธ์š”!๐Ÿ€'); + return; // ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•˜์ง€ ์•Š์•˜์œผ๋ฉด ํ•จ์ˆ˜ ์ข…๋ฃŒ + } + // ์ด๋ฏธ ๊ฐ™์€ ๋‚ด์šฉ์˜ ํˆฌ๋‘๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ + + const isDuplicate = todoList.some((todo) => todo.text === newTodo); //some ๋ฉ”์„œ๋“œ, ๋ฐฐ์—ด์˜ ๊ฐ ์š”์†Œ๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ, ์ฃผ์–ด์ง„ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์š”์†Œ๊ฐ€ ํ•˜๋‚˜๋ผ๋„ ์žˆ์œผ๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์š”์†Œ๊ฐ€ ์—†์œผ๋ฉด false๋ฅผ ๋ฐ˜ํ™˜ + if (isDuplicate) { + alert("์ด๋ฏธ ๋™์ผํ•œ ํˆฌ๋‘๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค!๐Ÿ‘๐Ÿป"); // ์•Œ๋ฆผ์ฐฝ์œผ๋กœ ์ค‘๋ณต ํˆฌ๋‘ ์•Œ๋ฆผ + todoInput.value = ""; + return; // ์ค‘๋ณต๋˜๋ฉด ํ•จ์ˆ˜ ์ข…๋ฃŒ + } + + todoList.push({ text: newTodo, completed: false }); // ๋ฐฐ์—ด์— ์ž…๋ ฅ ๊ฐ’ ์ €์žฅ + saveStorage(); // list์— ์ƒˆ๋กœ์šด todo๊ฐ€ ์ถ”๊ฐ€ ๋จ์œผ๋กœ์จ ๋ณ€๊ฒฝ๋˜์—ˆ์œผ๋‹ˆ ๋‹ค์‹œ localStorage์— todoList ์ €์žฅ + displayTodo(newTodo, false); + todoInput.value = ""; // ๋ฐฐ์—ด์— todo๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ Œ๋”๋ง ํ–ˆ๋‹ค๋ฉด input์„ ์ง€์›Œ์„œ ๋‹ค์‹œ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋„๋ก + updateCounts(); // ์ „์ฒด todo ๊ฐœ์ˆ˜์— +1 + } + + function saveStorage() { + localStorage.setItem("todos", JSON.stringify(todoList)); //localStorage๋Š” ๋ฌธ์ž์—ด ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋งŒ ์ €์žฅํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, JSON.stringify()๋ฅผ ์‚ฌ์šฉํ•ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด๋‚˜ ๋ฐฐ์—ด์„ JSON ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•œ ํ›„ ์ €์žฅ. ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ๋Š” JSON.parse() ์ด์šฉ + } // setItem(key,value) ํŠน์ • key์— ํ•ด๋‹น value ํ• ๋‹น + + function loadStorage() { + const storedTodos = localStorage.getItem("todos"); // ๊ธฐ์กด์— localStorage์— ์ €์žฅ๋˜์–ด์žˆ๋˜ ๋ฐฐ์—ด์„ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ, ๋งŒ์•ฝ ์—†๋‹ค๋ฉด null์ด ์ €์žฅ ๋จ + if (storedTodos) { + todoList = JSON.parse(storedTodos); + todoList.forEach((todo) => displayTodo(todo.text, todo.completed)); // todoList ๋ฐฐ์—ด์„ ์ˆœํšŒํ•˜๋ฉฐ ์ €์žฅ๋œ ๋ชจ๋“  todo๋ฅผ ํ™”๋ฉด์— ๋ Œ๋”๋ง + } + updateCounts(); // ์ƒˆ๋กœ ๊ณ ์นจ ์‹œ ๊ธฐ์กด todoList ๋ฐฐ์—ด ๋ถˆ๋Ÿฌ์™€์„œ ์ด ๊ฐœ์ˆ˜ ๋งž๊ฒŒ ๋ Œ๋”๋ง + } + + function displayTodo(todoText, isCompleted) { + const li = document.createElement("li"); // ์ƒˆ๋กœ์šด
  • ์š”์†Œ ์ƒ์„ฑ. ํ•˜๋‚˜์˜ todo๋ฅผ ๋‚˜ํƒ€๋ƒ„ + + const checkbox = document.createElement("input"); // ์ƒˆ๋กœ์šด input ์š”์†Œ checkbox ์ƒ์„ฑ + checkbox.type = "checkbox"; // ์ด ์š”์†Œ์˜ type = checkbox + checkbox.classList.add("todoCheckBox"); // ์Šคํƒ€์ผ๋ง์„ ์œ„ํ•ด ํด๋ž˜์Šค ๋ชฉ๋ก์— ํด๋ž˜์Šค ์ด๋ฆ„ ์ถ”๊ฐ€! ์ฆ‰ checkbox์— ํ• ๋‹น๋˜๋Š” ํด๋ž˜์Šค ์ด๋ฆ„์ด todo-checkbox + checkbox.checked = isCompleted; // isCompleted๊ฐ€ true๋ผ๋ฉด checkbox๊ฐ€ ์ฒดํฌ ๋จ + + checkbox.addEventListener("change", function () { // checkbox์˜ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€” ๋•Œ, ์ฆ‰ checked์˜ ์†์„ฑ์ด ๋ณ€๊ฒฝ๋  ๋•Œ (์‚ฌ์šฉ์ž๊ฐ€ ์ฒดํฌ๋ฐ•์Šค๋ฅผ ์ฒดํฌํ•˜๊ฑฐ๋‚˜ ํ•ด์ œํ•  ๋•Œ) ์‹คํ–‰๋  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ + toggleTodoCompletion(todoText); + li.querySelector("span").style.textDecoration = checkbox.checked ? "line-through" : "none"; + }); //
  • ์š”์†Œ์˜ ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ์ฐพ์•„ ์Šคํƒ€์ผ๋ง. ๋งŒ์•ฝ ์ฒดํฌ๋ฐ•์Šค๊ฐ€ ์ฒดํฌ ๋˜์–ด์žˆ์œผ๋ฉด? ์„ ์„ ๊ธ‹๊ณ  ํ•ด์ œ๋˜์–ด ์žˆ์œผ๋ฉด ์„ ์„ ์—†์•ค๋‹ค! + + const todoSpan = document.createElement("span"); //
  • ์š”์†Œ ์•ˆ์— ์“ฐ์—ฌ์งˆ ํ…์ŠคํŠธ๋ฅผ ์š”์†Œ๋กœ ์„ค์ • + todoSpan.classList.add("todoSpan"); + todoSpan.textContent = todoText; // ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ ๋ฐ›์€ input์˜ text๋ฅผ ๋ณ€์ˆ˜ todoSpan์˜ ํ…์ŠคํŠธ ๋‚ด์šฉ์œผ๋กœ ์ €์žฅ + if (isCompleted) { + todoSpan.style.textDecoration = "line-through"; + } + + const deleteBtn = document.createElement("button"); // ์ƒˆ๋กœ์šด