Spaces:
Running
Running
| <html> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width" /> | |
| <title>MERN Todo App</title> | |
| <link rel="stylesheet" href="style.css" /> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| </head> | |
| <body class="bg-gray-100 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8 max-w-md"> | |
| <div class="bg-white rounded-lg shadow-lg p-6"> | |
| <h1 class="text-2xl font-bold text-center mb-6 text-gray-800">Todo List</h1> | |
| <div class="flex mb-4"> | |
| <input | |
| type="text" | |
| id="todoInput" | |
| placeholder="Add a new task..." | |
| class="flex-1 px-4 py-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-blue-500" | |
| > | |
| <button | |
| id="addBtn" | |
| class="bg-blue-500 text-white px-4 py-2 rounded-r-lg hover:bg-blue-600 transition duration-200" | |
| > | |
| Add | |
| </button> | |
| </div> | |
| <ul id="todoList" class="space-y-2"> | |
| <!-- Todo items will be added here dynamically --> | |
| </ul> | |
| <div class="mt-4 text-center text-gray-500 text-sm"> | |
| <span id="taskCount">0 tasks</span> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| let todos = JSON.parse(localStorage.getItem('todos')) || []; | |
| function renderTodos() { | |
| const todoList = document.getElementById('todoList'); | |
| const taskCount = document.getElementById('taskCount'); | |
| todoList.innerHTML = ''; | |
| todos.forEach((todo, index) => { | |
| const li = document.createElement('li'); | |
| li.className = 'flex items-center justify-between bg-gray-50 p-3 rounded-lg'; | |
| li.innerHTML = ` | |
| <div class="flex items-center"> | |
| <input | |
| type="checkbox" | |
| ${todo.completed ? 'checked' : ''} | |
| onchange="toggleTodo(${index})" | |
| class="mr-3 h-4 w-4 text-blue-500 focus:ring-blue-400" | |
| > | |
| <span class="${todo.completed ? 'line-through text-gray-400' : 'text-gray-700'}"> | |
| ${todo.text} | |
| </span> | |
| </div> | |
| <button | |
| onclick="deleteTodo(${index})" | |
| class="text-red-500 hover:text-red-700 transition duration-200" | |
| > | |
| <i data-feather="trash-2" class="w-4 h-4"></i> | |
| </button> | |
| `; | |
| todoList.appendChild(li); | |
| }); | |
| taskCount.textContent = `${todos.length} ${todos.length === 1 ? 'task' : 'tasks'}`; | |
| feather.replace(); | |
| } | |
| function addTodo() { | |
| const input = document.getElementById('todoInput'); | |
| const text = input.value.trim(); | |
| if (text) { | |
| todos.push({ text, completed: false }); | |
| localStorage.setItem('todos', JSON.stringify(todos)); | |
| input.value = ''; | |
| renderTodos(); | |
| } | |
| } | |
| function toggleTodo(index) { | |
| todos[index].completed = !todos[index].completed; | |
| localStorage.setItem('todos', JSON.stringify(todos)); | |
| renderTodos(); | |
| } | |
| function deleteTodo(index) { | |
| todos.splice(index, 1); | |
| localStorage.setItem('todos', JSON.stringify(todos)); | |
| renderTodos(); | |
| } | |
| document.getElementById('addBtn').addEventListener('click', addTodo); | |
| document.getElementById('todoInput').addEventListener('keypress', (e) => { | |
| if (e.key === 'Enter') { | |
| addTodo(); | |
| } | |
| }); | |
| // Initial render | |
| renderTodos(); | |
| </script> | |
| </body> | |
| </html> | |