34179-vm/assets/js/main.js
Flatlogic Bot 3ee84ff2b8 final
2025-09-17 23:26:05 +00:00

179 lines
6.3 KiB
JavaScript

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 = `
<input type="checkbox" ${task.completed ? 'checked' : ''}>
<span>${escapeHTML(task.title)}</span>
<button class="delete-btn">&times;</button>
`;
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 = `
<div class="flower-daisy">
<div class="stem"></div>
<div class="leaf left"></div>
<div class="leaf right"></div>
<div class="flower-head">
<div class="flower-center"></div>
<div class="petal petal-${element.color}">
<div class="p1"></div>
<div class="p2"></div>
<div class="p3"></div>
<div class="p4"></div>
<div class="p5"></div>
<div class="p6"></div>
<div class="p7"></div>
<div class="p8"></div>
</div>
</div>
</div>
`;
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 => ({
'&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'" : '&#39;'
}[s]));
}
// --- Run App ---
init();
});