From 209dfb639f7a20faf14ab389689859556e5d577a Mon Sep 17 00:00:00 2001 From: yyj0917 Date: Thu, 5 Sep 2024 14:57:02 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat=20:=20task=20insert,=20delete,=20ui=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 39 ++++++++- script.js | 158 ++++++++++++++++++++++++++++++++++ style.css | 247 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 443 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index d241b1b..8709f3e 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,44 @@ -
+
+
+ +
+

+

Today

+
+ + + +
+ +
+ + +
+
+
diff --git a/script.js b/script.js index 355dcc2..b87edc5 100644 --- a/script.js +++ b/script.js @@ -1 +1,159 @@ //๐Ÿ˜CEOS 20๊ธฐ ํ”„๋ก ํŠธ์—”๋“œ ํŒŒ์ดํŒ…๐Ÿ˜ + +document.addEventListener('DOMContentLoaded', function () { + const currentDate = new Date(); + const today = document.querySelector('.today'); + const weekDays = document.querySelector('.week-days'); + const taskList = document.querySelector('.task-list'); + const modalBtn = document.querySelector('.btn-modal'); + const taskAdd = document.querySelector('.task-add'); + const taskSave = document.querySelector('.save'); + const backBtn = document.querySelector('.back'); + + let selectedDate = ''; // selected date + + // ์ผ์ฃผ์ผ ๋‚ ์งœ ์ƒ์„ฑ, ์˜ค๋Š˜ ๋‚ ์งœ ํ‘œ์‹œ + function loadWeekDays() { + weekDays.innerHTML = ''; + today.innerText = currentDate.toLocaleString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }); + + // ๋‚ ์งœ ๊ณ„์‚ฐ + const firstDayOfWeek = new Date(currentDate); + firstDayOfWeek.setDate(currentDate.getDate() - currentDate.getDay() + 1); // ์›”์š”์ผ(0: ์ผ์š”์ผ, 1: ์›”์š”์ผ) + + for (let i = 0; i < 7; i++) { + const day = new Date(firstDayOfWeek); + day.setDate(firstDayOfWeek.getDate() + i); + const dayElement = document.createElement('li'); + const dateKey = day.toISOString().split('T')[0]; + + // week set + const weekSpan = document.createElement('span'); + weekSpan.className = 'week'; + weekSpan.innerText = day.toLocaleString('en-US', { weekday: 'short' }); + + // day set + const daySpan = document.createElement('span'); + daySpan.className = 'day'; + daySpan.innerText = day.getDate(); + + dayElement.dataset.dateKey = dateKey; + dayElement.addEventListener('click', () => { + selectDate(dayElement); + loadTasks(dateKey); + }); + + // Today selected set + if (dateKey === new Date().toISOString().split('T')[0]) { + dayElement.classList.add('selected'); + selectedDate = dateKey; + // loadTasks(selectedDate); + } + + // ๊ฐœ๋ณ„ ์Šคํƒ€์ผ์„ ์œ„ํ•œ span tag ์‚ฝ์ž… + dayElement.appendChild(weekSpan); + dayElement.appendChild(daySpan); + weekDays.appendChild(dayElement); + } + } + // ์„ ํƒ๋œ ๋‚ ์งœ ํ‘œ์‹œ + function selectDate(dayElement) { + const selected = document.querySelector('.selected'); + if (selected) { + selected.classList.remove('selected'); + } + dayElement.classList.add('selected'); + } + + // load To Do List + function loadTasks(dateKey) { + taskList.innerHTML = ''; // ๊ธฐ์กด ํ•  ์ผ ๋ชฉ๋ก ์ง€์šฐ๊ธฐ + const tasks = JSON.parse(localStorage.getItem(dateKey)) || []; // LocalStorage์—์„œ ํ•ด๋‹น ๋‚ ์งœ์˜ ํ•  ์ผ ๊ฐ€์ ธ์˜ค๊ธฐ + + tasks.forEach((task, index) => { + addTaskToDOM(task, index); + }); + } + + + // Add To Do List -> DOM์— ์ถ”๊ฐ€ -> ํ™”๋ฉด์— ๋„์šฐ๊ธฐ์šฉ + function addTaskToDOM(task, index) { + const taskElement = document.createElement('article'); + taskElement.className = 'task'; + taskElement.innerHTML = ` +
+ ${task.time} +

${task.title}

+

${task.desc}

+ +
+ `; + taskElement.querySelector('.task-delete').addEventListener('click', function () { + const confirm = window.confirm('์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?'); + if (confirm) { + deleteTask(selectedDate, index); // ์‚ญ์ œ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ•  ์ผ ์‚ญ์ œ + } + }); + taskList.appendChild(taskElement); + } + + // Add Task -> LocalStorage์— ์ถ”๊ฐ€ + function addTaskToLocal(dateKey, task) { + const tasks = JSON.parse(localStorage.getItem(dateKey)) || []; + + // ์ž‘์„ฑ์‹œ๊ฐ„ + task.createdTime = new Date().toLocaleString('en-US', { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' }); + + tasks.push(task); + localStorage.setItem(dateKey, JSON.stringify(tasks)); + } + // Delete Task -> LocalStorage์—์„œ ์‚ญ์ œ -> ๊ธฐ์กด ๋ชฉ๋ก ๋ถˆ๋Ÿฌ์˜ค๊ณ , ๋ชฉ๋ก์—์„œ ์‚ญ์ œ ํ›„ ์‚ญ์ œ๋œ ๋ชฉ๋ก ์ €์žฅ...ํ  + function deleteTask(dateKey, taskIndex) { + const tasks = JSON.parse(localStorage.getItem(dateKey)) || []; + tasks.splice(taskIndex, 1); + localStorage.setItem(dateKey, JSON.stringify(tasks)); + loadTasks(dateKey); + } + + // Modal Button + modalBtn.addEventListener('click', () => { + modalBtn.style.display = 'none'; + taskAdd.style.display = 'flex'; + }); + + // ๋’ค๋กœ๊ฐ€๊ธฐ + backBtn.addEventListener('click', () => { + modalBtn.style.display = 'block'; + taskAdd.style.display = 'none'; + }); + + // Save Task + taskSave.addEventListener('click', function () { + const taskTitle = document.getElementById('task-title').value; + const taskDesc = document.getElementById('task-desc').value; + + + if (selectedDate) { // ๋‚ ์งœ๊ฐ€ ์„ ํƒ๋œ ๊ฒฝ์šฐ์—๋งŒ ์ €์žฅ + const newTask = { + title: taskTitle, + desc: taskDesc, + time: new Date().toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', second: 'numeric' }) + + }; + + // input field init + taskTitle = ''; + taskDesc = ''; + + addTaskToLocal(selectedDate, newTask); + loadTasks(selectedDate); + modalBtn.style.display = 'block'; + taskAdd.style.display = 'none'; + } + }); + + + loadWeekDays(); + loadTasks(selectedDate); + +}); \ No newline at end of file diff --git a/style.css b/style.css index 599136a..b060d4f 100644 --- a/style.css +++ b/style.css @@ -1 +1,248 @@ /* ๋ณธ์ธ์˜ ๋””์ž์ธ ๊ฐ๊ฐ์„ ์ตœ๋Œ€ํ•œ ๋ฐœํœ˜ํ•ด์ฃผ์„ธ์š”! */ +@font-face { + font-family: 'Pretendard-Regular'; + src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Regular.woff') format('woff'); + font-weight: 400; + font-style: normal; +} +@font-face { + font-family: 'SUIT-Regular'; + src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_suit@1.0/SUIT-Regular.woff2') format('woff2'); + font-weight: normal; + font-style: normal; +} + +* { + font-family: 'SUIT-Regular', sans-serif; + margin: 0; + padding: 0; + box-sizing: border-box; +} +.wrapper { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + background-color: #dfe2e5; +} +.container { + width: 360px; + height: 80vh; + margin: 0 auto; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + border-radius: 28px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + background-color: #fff; + padding: 20px 10px; +} + +/* header */ + +header { + width: 100%; + height: 15%; + padding: 10px; + display: flex; + flex-direction: column; + justify-content: center; + gap: 5px; +} +header h1 { + font-size: 32px; + font-weight: 1200; + color: #333; +} +header h2 { + font-size: 18px; + font-weight: 700; + color: #c0c0c0; +} + +/* nav */ + +nav { + width: 100%; + height: 10%; + display: flex; + align-items: center; +} +nav ul { + padding: 0 10px; + width: 100%; + display: flex; + justify-content: space-between; + gap: 10px; + list-style-type: none; + +} +nav ul li { + width: 14%; + border-radius: 10px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 5px; + cursor: pointer; +} +nav ul li:hover { + background-color: #d7e4ef; +} +nav .week { + font-size: 16px; + font-weight: 800; + color: #c0c0c0; +} +nav .day { + font-size: 14px; + font-weight: 900; + color: #333; +} +nav ul li.selected { + border-radius: 0; + color: #89bfeb; + border-bottom: 2px solid #89bfeb; + span { + color: #89bfeb; + } +} + +/* main */ + +main { + margin: 10px 0; + padding: 10px; + width: 100%; + height: 65%; + display: flex; + flex-direction: column; + gap: 10px; + overflow: auto; + border-top: 2px solid #f1f1f1; + border-bottom: 2px solid #f1f1f1; + /* background-color: aquamarine; */ +} +main article { + width: 100%; + height: auto; + padding: 0 10px; + display: flex; + justify-content: space-between; + align-items: center; + background-color: #f8f8ff; + border-radius: 10px; + + .task-detail { + position: relative; + width: 100%; + padding: 20px; + display: flex; + flex-direction: column; + gap: 5px; + + .task-time { + position: absolute; + top: 5px; + right: 5px; + font-size: 12px; + font-weight: 700; + color: gray; + text-decoration: underline; + } + .task-title { + font-size: 16px; + font-weight: 800; + color: #333; + } + .task-desc { + font-size: 14px; + font-weight: 700; + color: gray; + } + .task-delete { + position: absolute; + bottom: 10px; + right: 5px; + background-color: white; + color: black; + border-radius: 8px; + padding: 2px; + border: none; + cursor: pointer; + } + .task-delete:hover { + background-color: lightgray; + } + } +} + +/* footer */ + +footer { + width: 100%; + height: 10%; + display: flex; + justify-content: space-around; + align-items: center; + gap: 20px; +} +footer button.btn-modal{ + border: none; + width: 50px; + height: 50px; + border-radius: 50%; + background-color: #89bfeb; + color: #fff; + font-size: 18px; + font-weight: 800; + cursor: pointer; + font-size: 32px; + text-align: center; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); +} +footer button.btn-modal:hover { + background-color: #509ddc; +} +footer span { + width: 100%; + display: flex; + justify-content: center; + align-items: center; + gap: 20px; +} +footer span div { + width: auto; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 5px; +} +footer input { + width: 200px; + height: 30px; + border: none; + border-radius: 8px; + padding: 0 10px; + font-size: 14px; + font-weight: 800; + color: #333; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); +} +footer button.btn { + padding: 4px; + width: auto; + height: 30px; + border: none; + border-radius: 8px; + background-color: #f8f8ff; + color: #333; + font-size: 16px; + font-weight: 800; + text-align: center; + cursor: pointer; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); +} From d3ea273688b14497743ec56e020f53e2ef1f31ad Mon Sep 17 00:00:00 2001 From: yyj0917 Date: Thu, 5 Sep 2024 15:32:30 +0900 Subject: [PATCH 2/4] fix : constant variable assignment script.js #131~#147 --- script.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/script.js b/script.js index b87edc5..b0a0251 100644 --- a/script.js +++ b/script.js @@ -129,9 +129,10 @@ document.addEventListener('DOMContentLoaded', function () { // Save Task taskSave.addEventListener('click', function () { - const taskTitle = document.getElementById('task-title').value; - const taskDesc = document.getElementById('task-desc').value; - + const taskTitleInput = document.getElementById('task-title'); + const taskDescInput = document.getElementById('task-desc'); + const taskTitle = taskTitleInput.value; + const taskDesc = taskDescInput.value; if (selectedDate) { // ๋‚ ์งœ๊ฐ€ ์„ ํƒ๋œ ๊ฒฝ์šฐ์—๋งŒ ์ €์žฅ const newTask = { @@ -142,8 +143,8 @@ document.addEventListener('DOMContentLoaded', function () { }; // input field init - taskTitle = ''; - taskDesc = ''; + taskTitleInput.value = ''; + taskDescInput.value = ''; addTaskToLocal(selectedDate, newTask); loadTasks(selectedDate); From 93e6c31ac986fa58efa254de2221d2a31ae8bbd6 Mon Sep 17 00:00:00 2001 From: yyj0917 Date: Fri, 6 Sep 2024 18:39:22 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat=20:=20date=20select=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=EC=B6=94=EA=B0=80,=20fix=20:=20selected=20date=20?= =?UTF-8?q?=EA=B8=B0=EC=A4=80=20=EC=A0=80=EC=9E=A5=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 18 ++++++++------ script.js | 71 +++++++++++++++++++++++++++++++++++++++--------------- style.css | 23 ++++++++++++++---- 3 files changed, 80 insertions(+), 32 deletions(-) diff --git a/index.html b/index.html index 8709f3e..88d1e23 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ - Vanilla Todo + To Do List-yyj0917 @@ -13,7 +13,10 @@

-

Today

+ +

Today

+ +