Skip to content

Instantly share code, notes, and snippets.

@SH20RAJ
Created July 24, 2024 02:59
Show Gist options
  • Save SH20RAJ/ff4810b03a4292b5dace3d81a362e88f to your computer and use it in GitHub Desktop.
Save SH20RAJ/ff4810b03a4292b5dace3d81a362e88f to your computer and use it in GitHub Desktop.
Daily To-Do List
<!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>
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();
});
* {
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