Spaces:
Running
Running
| document.addEventListener('DOMContentLoaded', () => { | |
| const taskForm = document.getElementById('task-form'); | |
| const newTaskInput = document.getElementById('new-task'); | |
| const taskList = document.getElementById('task-list'); | |
| const emptyState = document.getElementById('empty-state'); | |
| let tasks = JSON.parse(localStorage.getItem('tasks')) || []; | |
| // Render tasks on page load | |
| renderTasks(); | |
| // Add new task | |
| taskForm.addEventListener('submit', (e) => { | |
| e.preventDefault(); | |
| const taskText = newTaskInput.value.trim(); | |
| if (taskText) { | |
| addTask(taskText); | |
| newTaskInput.value = ''; | |
| newTaskInput.focus(); | |
| } | |
| }); | |
| // Add task function | |
| function addTask(text) { | |
| const newTask = { | |
| id: Date.now(), | |
| text: text, | |
| completed: false | |
| }; | |
| tasks.unshift(newTask); // Add to beginning of array | |
| saveTasks(); | |
| renderTasks(); | |
| } | |
| // Delete task | |
| function deleteTask(id) { | |
| tasks = tasks.filter(task => task.id !== id); | |
| saveTasks(); | |
| renderTasks(); | |
| } | |
| // Toggle task completion | |
| function toggleTask(id) { | |
| tasks = tasks.map(task => { | |
| if (task.id === id) { | |
| return {...task, completed: !task.completed}; | |
| } | |
| return task; | |
| }); | |
| // Sort tasks: incomplete first | |
| tasks.sort((a, b) => { | |
| if (a.completed && !b.completed) return 1; | |
| if (!a.completed && b.completed) return -1; | |
| return 0; | |
| }); | |
| saveTasks(); | |
| renderTasks(); | |
| } | |
| // Save tasks to localStorage | |
| function saveTasks() { | |
| localStorage.setItem('tasks', JSON.stringify(tasks)); | |
| } | |
| // Render tasks to the DOM | |
| function renderTasks() { | |
| if (tasks.length === 0) { | |
| taskList.innerHTML = ''; | |
| emptyState.classList.remove('hidden'); | |
| return; | |
| } | |
| emptyState.classList.add('hidden'); | |
| // Sort tasks: incomplete first | |
| const sortedTasks = [...tasks].sort((a, b) => { | |
| if (a.completed && !b.completed) return 1; | |
| if (!a.completed && b.completed) return -1; | |
| return 0; | |
| }); | |
| taskList.innerHTML = sortedTasks.map(task => ` | |
| <li class="task-item ${task.completed ? 'completed' : ''} p-4 flex items-center justify-between transition-all duration-200 hover:bg-pink-50"> | |
| <div class="flex items-center space-x-3"> | |
| <button | |
| class="check-button w-6 h-6 rounded-full border-2 border-pink-300 flex items-center justify-center ${task.completed ? 'checked bg-pink-400 border-pink-400' : ''}" | |
| data-id="${task.id}" | |
| aria-label="${task.completed ? 'Mark as incomplete' : 'Mark as complete'}" | |
| > | |
| ${task.completed ? '<i data-feather="check" class="w-4 h-4 text-white"></i>' : ''} | |
| </button> | |
| <span class="task-text ${task.completed ? 'text-pink-400' : 'text-gray-700'}">${task.text}</span> | |
| </div> | |
| <div class="task-actions flex space-x-2"> | |
| <button | |
| class="delete-button text-pink-400 hover:text-pink-600 transition-colors" | |
| data-id="${task.id}" | |
| aria-label="Delete task" | |
| > | |
| <i data-feather="trash-2" class="w-5 h-5"></i> | |
| </button> | |
| </div> | |
| </li> | |
| `).join(''); | |
| // Add event listeners to new buttons | |
| document.querySelectorAll('.check-button').forEach(button => { | |
| button.addEventListener('click', (e) => { | |
| const id = parseInt(e.currentTarget.getAttribute('data-id')); | |
| toggleTask(id); | |
| }); | |
| }); | |
| document.querySelectorAll('.delete-button').forEach(button => { | |
| button.addEventListener('click', (e) => { | |
| const id = parseInt(e.currentTarget.getAttribute('data-id')); | |
| deleteTask(id); | |
| }); | |
| }); | |
| // Re-initialize Feather icons | |
| feather.replace(); | |
| } | |
| }); |