document.addEventListener('DOMContentLoaded', () => { // DOM Elements const taskForm = document.getElementById('task-form'); const taskInput = document.getElementById('task-input'); const taskList = document.getElementById('task-list'); const garden = document.getElementById('garden'); const soundToggle = document.getElementById('sound-toggle'); const ambientSound = document.getElementById('ambient-sound'); const soundOnIcon = document.getElementById('sound-on-icon'); const soundOffIcon = document.getElementById('sound-off-icon'); // App State let tasks = JSON.parse(localStorage.getItem('tasks')) || []; let gardenElements = JSON.parse(localStorage.getItem('gardenElements')) || []; const flowerColors = ['pink', 'yellow', 'purple', 'white']; // --- Initialization --- function init() { tasks.forEach(renderTask); // Filter out garden elements whose tasks are no longer completed or no longer exist const completedTaskIds = new Set(tasks.filter(t => t.completed).map(t => t.id)); gardenElements = gardenElements.filter(el => completedTaskIds.has(el.taskId)); gardenElements.forEach(renderGardenElement); saveState(); // Resync localStorage with the filtered elements } // --- State Management --- function saveState() { localStorage.setItem('tasks', JSON.stringify(tasks)); localStorage.setItem('gardenElements', JSON.stringify(gardenElements)); } // --- Task Management --- taskForm.addEventListener('submit', e => { e.preventDefault(); const title = taskInput.value.trim(); if (title) { const newTask = { id: Date.now(), title, completed: false }; tasks.push(newTask); renderTask(newTask); saveState(); taskInput.value = ''; } }); function renderTask(task) { const li = document.createElement('li'); li.dataset.id = task.id; if (task.completed) { li.classList.add('completed'); } li.innerHTML = ` ${escapeHTML(task.title)} `; taskList.appendChild(li); li.querySelector('input[type="checkbox"]').addEventListener('change', (e) => { toggleTaskCompletion(task.id, e.target.checked); }); li.querySelector('.delete-btn').addEventListener('click', () => { deleteTask(task.id); }); } function toggleTaskCompletion(id, isCompleted) { const taskIndex = tasks.findIndex(t => t.id === id); if (taskIndex > -1) { tasks[taskIndex].completed = isCompleted; const taskElement = taskList.querySelector(`[data-id='${id}']`); if (taskElement) { taskElement.classList.toggle('completed', isCompleted); } if (isCompleted) { addGardenElement(id); } else { removeGardenElement(id); } saveState(); } } function deleteTask(id) { tasks = tasks.filter(t => t.id !== id); const taskElement = taskList.querySelector(`[data-id='${id}']`); if (taskElement) { taskElement.remove(); } removeGardenElement(id); saveState(); } // --- Garden Management --- function addGardenElement(taskId) { if (gardenElements.some(el => el.taskId === taskId)) return; const newElement = { id: Date.now(), taskId: taskId, x: Math.random() * 80 + 10, // 10% to 90% to avoid edges color: flowerColors[Math.floor(Math.random() * flowerColors.length)] }; gardenElements.push(newElement); renderGardenElement(newElement); saveState(); } function renderGardenElement(element) { const el = document.createElement('div'); el.dataset.id = element.id; el.classList.add('garden-element', 'grow'); el.style.left = `${element.x}%`; el.innerHTML = `
`; garden.appendChild(el); } function removeGardenElement(taskId) { const elementToRemoveIdx = gardenElements.findIndex(el => el.taskId === taskId); if (elementToRemoveIdx > -1) { const elementToRemove = gardenElements[elementToRemoveIdx]; const el = garden.querySelector(`[data-id='${elementToRemove.id}']`); if (el) { el.classList.remove('grow'); el.classList.add('shrink'); setTimeout(() => { el.remove(); }, 500); } gardenElements.splice(elementToRemoveIdx, 1); saveState(); } } // --- Controls --- soundToggle.addEventListener('click', () => { if (ambientSound.paused) { ambientSound.play().catch(e => console.error("Audio play failed: ", e)); soundOnIcon.style.display = 'block'; soundOffIcon.style.display = 'none'; } else { ambientSound.pause(); soundOnIcon.style.display = 'none'; soundOffIcon.style.display = 'block'; } }); // --- Utility --- function escapeHTML(str) { return str.replace(/[&<>"']/g, s => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'" : ''' }[s])); } // --- Run App --- init(); });