Created
July 24, 2024 02:59
-
-
Save SH20RAJ/ff4810b03a4292b5dace3d81a362e88f to your computer and use it in GitHub Desktop.
Daily To-Do List
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Daily To-Do App</title> | |
<link rel="stylesheet" href="styles.css"> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="header"> | |
<h1>Daily To-Do List</h1> | |
<button id="reset-btn">Reset All Checked</button> | |
</div> | |
<div class="topbox"> | |
<input type="text" id="todo-input" placeholder="Add a new to-do"> | |
<div id="add-btn">+</div></div> | |
<div class="progress-bar" id="progress-bar"> | |
<div class="progress" id="progress"></div> | |
</div> | |
<table> | |
<thead> | |
<tr> | |
<th>To-Do</th> | |
<th>Action</th> | |
</tr> | |
</thead> | |
<tbody id="todo-list"></tbody> | |
</table> | |
<details> | |
<summary>Work Done Today</summary> | |
<ul id="completed-list"></ul> | |
</details> | |
</button> | |
<script src="app.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
document.addEventListener('DOMContentLoaded', () => { | |
const input = document.getElementById('todo-input'); | |
const addBtn = document.getElementById('add-btn'); | |
const todoList = document.getElementById('todo-list'); | |
const completedList = document.getElementById('completed-list'); | |
const resetBtn = document.getElementById('reset-btn'); | |
const progressBar = document.getElementById('progress-bar'); | |
const progress = document.getElementById('progress'); | |
let todos = JSON.parse(localStorage.getItem('todos')) || []; | |
const saveTodos = () => { | |
localStorage.setItem('todos', JSON.stringify(todos)); | |
}; | |
const updateProgressBar = () => { | |
const total = todos.length; | |
const completed = todos.filter(todo => todo.checked).length; | |
const percentage = total === 0 ? 0 : (completed / total) * 100; | |
progress.style.width = `${percentage}%`; | |
}; | |
const renderTodos = () => { | |
todoList.innerHTML = ''; | |
completedList.innerHTML = ''; | |
todos.forEach((todo, index) => { | |
const tr = document.createElement('tr'); | |
tr.classList.add('todo-item'); | |
tr.draggable = true; | |
if (todo.checked) { | |
tr.classList.add('checked'); | |
} | |
const tdText = document.createElement('td'); | |
tdText.textContent = todo.text; | |
tdText.addEventListener('click', () => { | |
todo.checked = !todo.checked; | |
saveTodos(); | |
renderTodos(); | |
updateProgressBar(); | |
}); | |
const tdAction = document.createElement('td'); | |
const checkbox = document.createElement('input'); | |
checkbox.type = 'checkbox'; | |
checkbox.checked = todo.checked; | |
checkbox.addEventListener('change', () => { | |
todo.checked = !todo.checked; | |
saveTodos(); | |
renderTodos(); | |
updateProgressBar(); | |
}); | |
const deleteBtn = document.createElement('span'); | |
deleteBtn.textContent = 'X'; | |
deleteBtn.addEventListener('click', () => { | |
todos.splice(index, 1); | |
saveTodos(); | |
renderTodos(); | |
updateProgressBar(); | |
}); | |
const handle = document.createElement('span'); | |
handle.textContent = '⇅'; | |
handle.classList.add('drag-handle'); | |
tr.appendChild(tdText); | |
tr.appendChild(tdAction); | |
tdAction.appendChild(checkbox); | |
tdAction.appendChild(handle); | |
tdAction.appendChild(deleteBtn); | |
if (todo.checked) { | |
completedList.appendChild(tr); | |
} else { | |
todoList.appendChild(tr); | |
} | |
tr.addEventListener('dragstart', (e) => { | |
e.dataTransfer.setData('text/plain', index); | |
tr.classList.add('dragging'); | |
}); | |
tr.addEventListener('dragend', () => { | |
tr.classList.remove('dragging'); | |
}); | |
}); | |
}; | |
addBtn.addEventListener('click', () => { | |
const todoText = input.value.trim(); | |
if (todoText) { | |
todos.push({ text: todoText, checked: false }); | |
saveTodos(); | |
renderTodos(); | |
updateProgressBar(); | |
input.value = ''; | |
} | |
}); | |
input.addEventListener('keypress', (e) => { | |
if (e.key === 'Enter') { | |
addBtn.click(); | |
} | |
}); | |
resetBtn.addEventListener('click', () => { | |
todos.forEach(todo => todo.checked = false); | |
saveTodos(); | |
renderTodos(); | |
updateProgressBar(); | |
}); | |
todoList.addEventListener('dragover', (e) => { | |
e.preventDefault(); | |
const draggingItem = document.querySelector('.dragging'); | |
const siblings = [...todoList.querySelectorAll('.todo-item:not(.dragging)')]; | |
const nextSibling = siblings.find(sibling => e.clientY <= sibling.offsetTop + sibling.offsetHeight / 2); | |
todoList.insertBefore(draggingItem, nextSibling); | |
}); | |
completedList.addEventListener('dragover', (e) => { | |
e.preventDefault(); | |
const draggingItem = document.querySelector('.dragging'); | |
const siblings = [...completedList.querySelectorAll('.todo-item:not(.dragging)')]; | |
const nextSibling = siblings.find(sibling => e.clientY <= sibling.offsetTop + sibling.offsetHeight / 2); | |
completedList.insertBefore(draggingItem, nextSibling); | |
}); | |
todoList.addEventListener('dragend', () => { | |
const reorderedTodos = [...todoList.querySelectorAll('.todo-item')].map(tr => { | |
const text = tr.querySelector('td').textContent; | |
const checked = tr.querySelector('input').checked; | |
return { text, checked }; | |
}); | |
const completedTodos = [...completedList.querySelectorAll('.todo-item')].map(tr => { | |
const text = tr.querySelector('td').textContent; | |
const checked = tr.querySelector('input').checked; | |
return { | |
text, checked }; | |
}); | |
todos = reorderedTodos.concat(completedTodos); | |
saveTodos(); | |
updateProgressBar(); | |
}); | |
completedList.addEventListener('dragend', () => { | |
const reorderedTodos = [...todoList.querySelectorAll('.todo-item')].map(tr => { | |
const text = tr.querySelector('td').textContent; | |
const checked = tr.querySelector('input').checked; | |
return { text, checked }; | |
}); | |
const completedTodos = [...completedList.querySelectorAll('.todo-item')].map(tr => { | |
const text = tr.querySelector('td').textContent; | |
const checked = tr.querySelector('input').checked; | |
return { text, checked }; | |
}); | |
todos = reorderedTodos.concat(completedTodos); | |
saveTodos(); | |
updateProgressBar(); | |
}); | |
renderTodos(); | |
updateProgressBar(); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* { | |
box-sizing: border-box; | |
margin: 0; | |
padding: 0; | |
} | |
body { | |
font-family: Arial, sans-serif; | |
background-color: #f0f0f0; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
height: 100vh; | |
} | |
.container { | |
background-color: #fff; | |
padding: 20px; | |
border-radius: 5px; | |
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); | |
width: 100%; | |
height: 100vh; | |
display: flex; | |
flex-direction: column; | |
overflow: hidden; | |
} | |
.header { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
} | |
h1 { | |
margin: 0; | |
} | |
.topbox { | |
display : flex; | |
align-items:center; | |
gap: 10px; | |
} | |
input { | |
width: 80%; | |
padding: 10px; | |
margin: 10px 0; | |
border: 0; | |
border-bottom: 1px solid #ccc; | |
border-radius: 3px; | |
} | |
#add-btn { | |
width : 20%; | |
font-size:40px; | |
text-align:center; | |
} | |
button { | |
padding: 10px; | |
background-color: #007bff; | |
color: #fff; | |
border: none; | |
border-radius: 3px; | |
cursor: pointer; | |
margin: 10px 0; | |
align-self: flex-start; | |
} | |
button:hover { | |
background-color: #0056b3; | |
} | |
.progress-bar { | |
width: 100%; | |
height: 20px; | |
background-color: #e0e0e0; | |
border-radius: 10px; | |
margin: 10px 0; | |
} | |
.progress { | |
height: 100%; | |
background-color: #4caf50; | |
border-radius: 10px; | |
width: 0%; | |
} | |
table { | |
width: 100%; | |
border-collapse: collapse; | |
overflow-y: auto; | |
max-height: 50vh; | |
} | |
th, td { | |
padding: 10px; | |
border-bottom: 1px solid #ccc; | |
text-align: left; | |
} | |
th { | |
background-color: #f8f8f8; | |
} | |
.todo-item.checked { | |
text-decoration: line-through; | |
color: #888; | |
} | |
details { | |
margin-top: 20px; | |
overflow-y: auto; | |
} | |
details summary { | |
font-weight: bold; | |
cursor: pointer; | |
} | |
details ul { | |
list-style-type: none; | |
padding: 0; | |
max-height: 20vh; | |
overflow-y: auto; | |
} | |
details li { | |
padding: 10px; | |
border: 1px solid #ccc; | |
border-radius: 3px; | |
margin: 5px 0; | |
background-color: #f8f8f8; | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
} | |
.drag-handle { | |
cursor: grab; | |
} | |
.drag-handle:active { | |
cursor: grabbing; | |
} | |
td:nth-child(2) { | |
display: flex; | |
gap: 8px; | |
align-items : center; | |
} | |
td:first-child { | |
width:100%; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment