cute-task-tracker / script.js
iProsto's picture
Create a todo list site. Minimalistic, easy to use and user-friendly, cute. Opportunities: add a new task, remove any task, mark as done, mark as undone. Use localstorage for tasks. Sort undone tasks to the top of the list
8104128 verified
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();
}
});