As an expert developer and tutor could you rate these files' code and then provide these files after improvement?

// ui.js
import { getCurrentProject, getState, setCurrentProjectIndex, updateTodo, addTodo,addProject } from "./app.js";
import { StorageManager } from "./localStorage.js";
import { Todo } from "./todo.js";

/**
 * Render the list of projects in the sidebar.
 * @param {Array} projects - Array of Project instances.
 */
export function renderProjects(projects) {
    const projectContainer = document.querySelector('#project-list');
    projectContainer.innerHTML = ''; // Clear existing projects

    projects.forEach((project, index) => {
        const projectElement = document.createElement('li');
        projectElement.textContent = project.name;
        projectElement.classList.add('project-item');
        projectElement.setAttribute('data-index', index);
        projectElement.setAttribute('tabindex', '0'); // Make focusable

        projectContainer.appendChild(projectElement);
    });

    highlightSelectedProject(getState().currentProjectIndex);

    const projectIcon = document.createElement('i');
    projectIcon.className = 'fas fa-folder';
    // projectElement.prepend(projectIcon);
}


/**
 * Highlight the selected project in the sidebar.
 * @param {number} index – Index of the selected project.
 */
function highlightSelectedProject(index) {
    const items = document.querySelectorAll('#project-list li')
    items.forEach((item, i) => {
        item.classList.toggle('selected', i === index);
    });
}



/**
 * Render the todos for the selected project.
 * @param {Project} project – The Project instance whose todos are to be rendered.
 */
export function renderTodos(project) {
    const todoContainer = document.querySelector("#todo-container");
    todoContainer.innerHTML = ""; // Clear existing todos

    if (!project || !project.todos) {
        console.error("Invalid project or no todos available");
        return;
    }

    project.todos.forEach((todo) => {
        const todoElement = createTodoElement(todo);
        todoContainer.appendChild(todoElement);
    });
}

// Separate function to create a todo element
/**
 * Create a DOM element for a single todo item.
 * @param {Todo} todo – The todo item to create an element for.
 * @returns {HTMLElement} The DOM element representing the todo.
 */
function createTodoElement(todo) {
    const todoElement = document.createElement('div');
    todoElement.classList.add('todo-item', `priority-${todo.priority}`);
    todoElement.dataset.id = todo.id

    // Todo title and Due Date
    const todoInfo = document.createElement('span');
    todoInfo.textContent = `${todo.title} – Due: ${todo.dueDate}`;
    todoInfo.classList.add('todo-info');
    todoElement.appendChild(todoInfo);

    const checkbox = document.createElement('input');
    checkbox.type = 'checkbox';
    checkbox.checked = todo.completed;
    checkbox.addEventListener('change', () => {
        todo.toggleCompletion();
        updateTodoStatus(todo);
    });    

    todoElement.prepend(checkbox);

    function updateTodoStatus(todo) {
        StorageManager.saveProjects(getState().projects);
        if (todo.completed) {
            todoElement.classList.add('completed');
        } else {
            todoElement.classList.remove('completed');
        }
    }

    if (todo.tags && todo.tags.length > 0) {
        const tagsContainer = document.createElement('div');
        tagsContainer.classList.add('tags-container');
        todo.tags.forEach((tag) => {
            const tagElement = document.createElement('span');
            tagElement.classList.add('tag');
            tagElement.textContent = tag;
            tagsContainer.appendChild(tagElement);
        });
        todoElement.appendChild(tagsContainer);
    }

    // Edit button
    const editButton = createButton('fas fa-edit', 'edit-button');
    // Delete button
    const deleteButton = createButton('Delete', 'delete-button');
    
    todoElement.appendChild(editButton);
    todoElement.appendChild(deleteButton);    

    // Apply priority-based styling
    todoElement.classList.add(`priority-${todo.priority}`);

    return todoElement;
}

function createButton(text, className) {
    const button = document.createElement('button');
    const icon = document.createElement('i');
    icon.className = iconClass;
    button.appendChild(icon);
    button.textContent = text;
    button.classList.add(className);
    return button;
}

/**
 * Set up interactions for todo items (edit, delete).
 */
export function setupTodoInteraction() {
    const todoContainer = document.querySelector('#todo-container');

    // Handle edit and delete buttons using event delegation
    todoContainer.addEventListener('click', (event) => {
        const target = event.target;
        const todoElement = target.closest('.todo-item');
        if (!todoElement) return;

        const todoId = todoElement.getAttribute('data-id');
        const currentProject = getCurrentProject();
        const todo = currentProject.getTodoById(todoId);

        if (!todo) {
            console.error(`Todo with ID: ${todoId} not found`)
            return;
        }

        if (target.matches('.edit-button')) {
            showEditForm(todo);
        }

        if (target.matches('.delete-button')) {
            handleDeleteTodo(todoId, currentProject);
        }
    });
}

/**
 * Handle deleting a todo.
 * @param {string} todoId – ID of the todo to delete.
 * @param {Project} project – The project containing the todo.
 */
function handleDeleteTodo(todoId, project) {
    if (confirm('Are you sure you want to delete this task?')) {
        project.removeTodo(todoId);
        StorageManager.saveProjects(getState().projects);
        renderTodos(project);
    }
}

/**
 * Show the edit form modal with the current task data.
 * @param {Todo} todo – The todo to edit.
 */
function showEditForm(todo) {
    // Fill in the form with current todo data
    document.querySelector("#edit-title").value = todo.title;
    document.querySelector("#edit-description").value = todo.description;
    document.querySelector("#edit-due-date").value = todo.dueDate;
    document.querySelector("#edit-priority").value = todo.priority;

    const modal = document.querySelector("#edit-task-modal");
    if (!modal) {
        console.error("Edit Task Modal not found in the DOM");
        return;
    }

    modal.style.display = "block";
    modal.setAttribute('aria-hidden', 'false');
    modal.querySelector("#edit-title").focus();
    document.body.classList.add('modal-open'); // Prevent background scrolling

    const saveButton = document.querySelector('#save-changes-button');
    const cancelButton = document.querySelector('#cancel-button');
    const closeButton = document.querySelector('.close-button');

    /**
     * Handle saving changes to a todo.
     * @param {Todo} todo – The todo being edited.
     */
    function saveChangesHandler() {
        const updatedTitle = document.querySelector("#edit-title").value.trim();        
        const updatedDescription = document.querySelector("#edit-description").value.trim();
        const updatedDueDate = document.querySelector("#edit-due-date").value;
        const updatedPriority = document.querySelector("#edit-priority").value;

        if (!updatedTitle || !updatedDueDate) {
            showToast("Title and Due Date are required.");
            return;
        }

        // Update todo properties
        todo.title = updatedTitle;
        todo.description = updatedDescription;
        todo.dueDate = updatedDueDate;
        todo.priority = updatedPriority;

        try {
            updateTodo(todo); // Update in state and save
            closeModal();
        } catch (error) {
            console.error("Error updating todo:", error);
        }
    }

    /**
     * Function to close the edit modal.
     */
    function closeModal() {
        const modal = document.querySelector('#edit-task-modal');
        if (modal) {
            modal.style.display = "none";
            modal.setAttribute('aria-hidden', 'true');
            document.body.classList.remove('modal-open');
        }
    
        // Remove event listeners to prevent duplicate handlers
        saveButton.removeEventListener('click', saveChangesHandler);
        cancelButton.removeEventListener('click', closeModal);
        closeButton.removeEventListener('click', closeModal);    
        window.removeEventListener('keydown', escKeyHandler);
        window.removeEventListener('click', outsideClickHandler);
    }

    function escKeyHandler(event) {
        if (event.key === 'Escape') {
            closeModal();
        }
    }
    
    function outsideClickHandler(event) {
        const modal = document.querySelector('#edit-task-modal');
        if (event.target === modal) {
            closeModal();
        }
    }

    // Add event listeners
    saveButton.addEventListener('click', saveChangesHandler);
    cancelButton.addEventListener('click', closeModal);
    closeButton.addEventListener('click', closeModal);
    window.addEventListener('keydown', escKeyHandler);
    window.addEventListener('click', outsideClickHandler);
}

/**
 * Setup project selection interactions.
 */
export function setupProjectSelection() {
    const projectContainer = document.querySelector('#project-list');

    projectContainer.addEventListener('click', (event) => {
        if (event.target && event.target.matches('li.project-item')) {
            const index = parseInt(event.target.getAttribute('data-index'));
            setCurrentProjectIndex(index);
            highlightSelectedProject(index);
            const currentProject = getState().projects[index];
            renderTodos(currentProject);
        }
    });

    // Accessibility: Allow selection via keyboard
    projectContainer.addEventListener('keydown', (event) => {
        if (event.key === 'Enter' && event.target.matches('li.project-item')) {
            const index = parseInt(event.target.getAttribute('data-index'));
            setCurrentProjectIndex(index);
            highlightSelectedProject(index);
            const currentProject = getState().projects[index];
            renderTodos(currentProject);
        }
    });
}

/**
 * Initialize UI interactions.
 */
export function initializeUI() {
    setupProjectSelection();
    setupTodoInteraction();
    setupSidebarToggle();
    setupFormValidation();
    setupDragAndDrop();
    setupThemeToggle();
}

/**
 * Function to handle adding a new todo.
 */
function handleAddTodo() {
    try {
        const title = document.querySelector('#todo-title').value;
        const description = document.querySelector('#todo-description').value;
        const dueDate = document.querySelector('#todo-due-date').value;
        const priority = document.querySelector('#todo-priority').value;
        const tagsInput = document.querySelector('#todo-tags').value;
        const tags = tagsInput.split(',').map((tag) => tag.trim()).filter((tag) => tag);

        if (title && dueDate) { // Ensure title and due date are provided
            addTodo(title, description, dueDate, priority, tags); // Call function to add a new todo
            clearTodoInputs();
        } else {
            showToast('Please fill in both title and due date.'); // Alert if fields are empty
        }
    } catch (error) {
        console.error('Error adding todo:', error);
    }
}

/**
 * Function to handle adding a new project.
 */
function handleAddProject() {
    try {
        const projectName = document.querySelector('#project-name').value.trim();

        // Call function to add a new project
        if (projectName) {
            addProject(projectName);
            document.querySelector('#project-name').value = ''; // Clear input field
        } else {
            showToast('Please enter a project name.') // Alert if project name is empty
        }
    } catch (error) {
        console.error('Error adding project:', error);
    }
}

/**
 * Function to clear todo input fields
 */
function clearTodoInputs() {
    document.querySelector('#todo-title').value = ''; // Clear input field after adding
    document.querySelector('#todo-description').value = '';
    document.querySelector('#todo-due-date').value = '';
    document.querySelector('#todo-priority').value = 'low'; // Reset priority to default
}

// Function to show alert messages
function showAlert(message) {
    const alertBox = document.createElement('div');
    alertBox.classList.add('alert');
    alertBox.textContent = message;

    const main = document.querySelector('main');
    main.appendChild(alertBox);

    // alertBox.style.display = 'block';
    setTimeout(() => {
        // alertBox.style.display = 'none';
        alertBox.classList.add('fade-out');
        alertBox.addEventListener('transitionend', () => {
            alertBox.remove();
        });
    }, 3000);
}

/**
 * Set up event listeners for the application.
 */
export function setupEventListeners() {
    document.addEventListener('click', (event) => {
        if (event.target.matches('#add-todo-button')) {
            handleAddTodo();
        }
        if (event.target.matches('#add-project-button')) {
            handleAddProject();
        }
    });
}

export function setupSidebarToggle() {
    const sidebar = document.querySelector('.sidebar');
    const toggleButton = document.querySelector('#sidebar-toggle');

    toggleButton.addEventListener('click', () => {
        sidebar.classList.add('collapsed');
    });
}

function setupFormValidation() {
    const todoTitleInput = document.querySelector('#todo-title');

    todoTitleInput.addEventListener('input', () => {
        if (todoTitleInput.value.trim() === '') {
            todoTitleInput.classList.add('invalid');
            todoTitleInput.setCustomValidity('Title is required.');
        } else {
            todoTitleInput.classList.remove('invalid');
            todoTitleInput.setCustomValidity('');
        }
    })
}

export function setupDragAndDrop() {
    const todoContainer = document.querySelector('#todo-container');
    new Sortable(todoContainer, {
        animation: 150,
        onEnd: function(/** Event */ evt) {
            const itemEl = evt.item; // dragged HTMLElement
            const fromIndex = evt.oldIndex;
            const toIndex = evt.newIndex;
            updateTodoOrder(fromIndex, toIndex);
        },
    });
}

function updateTodoOrder(fromIndex, toIndex) {
    const currentProject = getCurrentProject();
    const movedTodo = currentProject.todos.splice(fromIndex, 1)[0];
    currentProject.todos.splice(toIndex, 0, movedTodo);
    StorageManager.saveProjects(getState().projects);
}

function showToast(message) {
    const toastContainer = document.querySelector('#toast-container');
    const toast = document.createElement('div');
    toast.classList.add('toast');
    toast.textContent = message;

    setTimeout(() => {
        toast.remove();
    }, 4000);
}

export function setupThemeToggle() {
    const themeToggle = document.querySelector('#theme-toggle');

    themeToggle.addEventListener('click', () => {
        const currentTheme = document.documentElement.getAttribute('data-theme');
        const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
        document.documentElement.setAttribute('data-theme', newTheme);
        localStorage.setItem('theme', newTheme);
        // Update icon
    const icon = themeToggle.querySelector('i');
    icon.className = newTheme === 'dark' ? 'fas fa-sun' : 'fas fa-moon';
    });

    // On load, set theme from localStorage
    const savedTheme = localStorage.getItem('theme') || 'light';
    document.documentElement.setAttribute('data-theme', savedTheme);
}

// todo.js

import { v4 as uuidv4 } from 'uuid'; // Ensure you have installed the `uuid` package via npm

const PRIORITY_LEVELS = {
    LOW: 'low',
    MEDIUM: 'medium',
    HIGH: 'high',
};

/**
 * Represents a single Todo item.
 */
export class Todo {
    /**
     * Creates a new Todo instance.
     * @param {string} title – The title of the todo.
     * @param {string} [description=''] – The description of the todo.
     * @param {string} dueDate – The due date of the todo in YYYY-MM-DD format.
     * @param {string} priority – The priority level ('low', 'medium', 'high').
     * @param {string} [notes=''] – Additional notes for the todo.
     * @param {string} [id] – Unique identifier for the todo.
     */
    constructor(title, description = '', dueDate, priority, notes = '', id = uuidv4(), tags = []) {
        // Data Validation
        if (!title || typeof title !== 'string') {
            throw new Error('Title is required and must be a string.');
        }
        if (!dueDate || isNaN(Date.parse(dueDate))) {
            throw new Error('A valid Due Date is required');
        }
        if (!Object.values(PRIORITY_LEVELS).includes(priority)) {
            throw new Error(`Priority must be one of ${Object.values(PRIORITY_LEVELS).join(', ')}.`);
        }

        // Object.defineProperty(this, 'id', {
        //     value: id,
        //     writable: false,
        //     enumerable: true,
        // });

        this.id = id; // Robust unique ID generation
        this.title = title;
        this.description = description;
        this.dueDate = dueDate;
        this.priority = priority;
        this.notes = notes;
        this.completed = false; // Track completion status
        this.subtasks = []; // Array to hold subtasks if needed
        this.recurrence = null; // For recurring tasks
        this.checklist = [];
        this.tags = tags;
    }

    /**
     * Toggle the completion status of todo
     */
    toggleCompletion() {
        this.completed = !this.completed;
        return this;
    }

    /**
     * Add a subtask to the todo.
     * @param {Todo} subtask – The subtask to add.
     */
    addSubtask(subtask) {
        if (subtask instanceof Todo) {
            this.subtasks.push(subtask);
        } else {
            throw new Error('Subtask must be an instance of Todo.');
        }
    }

    /**
     * Remove a subtask from the todo by ID.
     * @param {string} subtaskId – The ID of the subtask to remove.
     */
    removeSubtask(subtaskId) {
        this.subtasks = this.subtasks.filter((st) => st.id !== subtaskId);
    }
}

// project.js

import { Todo } from './todo.js';

/**
 * Represents a project containing multiple todos.
 */
export class Project {
    /**
     * Creates a new Project instance.
     * @param {string} name – The name of the project.
     */
    constructor(name) {
        if (!name || typeof name !== 'string') {
            throw new Error('Project name is required and must be a string.');
        }

        this.name = name;
        /** @type {Todo[]} */
        this.todos = []; // Array to hold todos
    }

    /**
     * Add a new Todo to the project.
     * @param {Todo} todo – The todo instance to add.
     * @returns {boolean} True if added successfully, false otherwise.
     */
    addTodo(todo) {
        if (todo instanceof Todo) {
            this.todos.push(todo);
            return true;
        } else {
            console.error('Only instances of Todo can be added.');
            return false;
        }
    }

    /**
     * Remove a todo by its ID.
     * @param {*} todoId 
     */
    removeTodo(todoId) {
        const initialLength = this.todos.length;
        this.todos = this.todos.filter((t) => t.id !== todoId); // Remove the todo
        if (this.todos.length === initialLength) {
            console.warn(`Todo with ID ${todoId} not found.`);
        }
    }

    /**
     * Get a todo by its ID.
     * @param {string} todoId – The ID of the todo to retrieve.
     * @returns {Todo|null} The todo instance or null if not found.
     */
    getTodoById(todoId) {
        return this.todos.find((t) => t.id === todoId) || null;
    }

    /**
     * Update a todo's details.
     * @param {Todo} updatedTodo – The updated Todo instance.
     * @returns {boolean} True if updated successfully, false otherwise.
     */
    updateTodo(updatedTodo) {
        const index = this.todos.findIndex((t) => t.id === updatedTodo.id);
        if (index !== -1) {
            this.todos[index] = updatedTodo;
            return true;
        } else {
            console.error(`Todo with ID ${updatedTodo.id} not found.`);
            return false;
        }
    }

    /**
     * Toggle completion status of a todo by its ID.
     * @param {string} todoId – The ID of the todo to toggle.
     * @returns {boolean} True if toggled successfully, false otherwise.
     */
    toggleTodoCompletion(todoId) {
        const todo = this.getTodoById(todoId);
        if (todo) {
            todo.toggleCompletion();
            return true;
        } else {
            console.error(`Todo with ID ${todoId} not found.`);
            return false;
        }
    }

    /**
     * Get all completed todos.
     * @returns {Todo[]} Array of completed todos.
     */
    getCompletedTodos() {
        return this.todos.filter((todo) => todo.completed);
    }
}

// app.js

import { Project } from './project.js';
import { Todo } from './todo.js';
import { StorageManager } from './localStorage.js';
import { renderTodos, renderProjects } from './ui.js';

/**
 * Application state encapsulated in an object.
 */
const state = {
  /** @type {Project[]} */
  projects: [],
  /** @type {number} */
  currentProjectIndex: 0
};

/**
 * Getter for the application state.
 * @returns {Object} The current state.
 */
export function getState() {
  return { ...state }; // Return a shallow copy to prevent direct mutation.
}

/**
 * Returns a shallow copy of the projects array. To prevent mutations.
 * @returns {Object[]} Array of Project instances.
 */
export function getProjects() {
  return [...state.projects];
}

/**
 * Gets the index of the current project.
 * @returns {number} The current project index.
 */
export function getCurrentProjectIndex() {
  return state.currentProjectIndex;
}

/**
 * Gets the current project instance.
 * @returns {Project} The current project.
 */
export function getCurrentProject() {
  return state.projects[state.currentProjectIndex];
}

/**
 * Sets the current project index and renders its todos.
 * @param {number} index – The index of the project to set as current.
 */
export function setCurrentProjectIndex(index) {
  if (index >= 0 && index < state.projects.length) {
    state.currentProjectIndex = index;
    renderTodos(state.projects[index]);
  } else {
    console.error('Invalid project index.');
  }
}

// export function selectProject(index) {
//   if (index => 0 && index < projectsArray.length) {
//     currentProjectIndex = index;
//     renderTodos(projectsArray[index]);
//   } else {
//     console.error('Invalid project index');
//   }
// }

/**
 * Initializes the application by loading projects and rendering them.
 */
export function initializeApp() {
  // Load existing projects from localStorage on startup
  const loadedProjects = StorageManager.loadProjects();

  if (loadedProjects.length > 0) {
    state.projects = loadedProjects;
  } else {
    // Create a default project if none exist
    const defaultProject = new Project('Default Project');
    state.projects.push(defaultProject);
    StorageManager.saveProjects(state.projects);
  }

  // Render the loaded or default projects
  renderProjects(state.projects);
  // renderTodos(getCurrentProject());
  setCurrentProjectIndex(0);
}

/**
 * Adds a new todo to the current project
 * @param {string} title – The title of the todo.
 * @param {string} description – The description of the todo.
 * @param {string} dueDate – The due date of the todo.
 * @param {string} priority – The priority of the todo.
 */
export function addTodo(title, description, dueDate, priority) {
  const currentProject = getCurrentProject(); // Use selected project

  if (!currentProject) {
    console.error('No current project selected');
    return;
  }

  try {
    const newTodo = new Todo(title, description, dueDate, priority);
    currentProject.addTodo(newTodo);
    // Save updated projects to localStorage
    StorageManager.saveProjects(state.projects);

    // Render todos for the current project
    renderTodos(currentProject);
  } catch (error) {
    console.error('Error adding todo:', error);
  }
  // return newTodo; // Return the created Todo object
}

/**
 * Adds a new project to the application.
 * @param {string} projectName – The name of the new project.
 */
export function addProject(projectName) {
  if (!projectName || typeof projectName !== 'string') {
    console.error('Invalid project name');
    return;
  }
  try {
    const newProject = new Project(projectName);
    state.projects.push(newProject);
    // Save updated projects to localStorage
    StorageManager.saveProjects(state.projects);

    // Re-render the projects list
    renderProjects(state.projects);
  } catch (error) {
    console.error('Error adding project:', error);
  }
}

// Function to update a todo
/**
 * Updates the existing todo in the current project.
 * @param {Todo} updatedTodo – The todo instance with updated details.
 * @returns 
 */
export function updateTodo(updatedTodo) {
  const currentProject = getCurrentProject();
  if (!currentProject) {
    console.error('No current project selected.');
    return;
  }

  try {
    currentProject.updateTodo(updatedTodo);
    StorageManager.saveProjects(state.projects);
    renderTodos(currentProject);
  } catch (error) {
    console.error('Error updating todo:', error);
  }
}

// localStorage.js

import { Project } from './project.js';
import { Todo } from './todo.js';

/**
 * Manages saving and loading projects to and from localStorage.
 */
export class StorageManager {
    /**
     * Save projects to localStorage.
     * @param {Project[]} projects – Array of Project instances.
     */
    static saveProjects(projects) {
        try {
            const serializedProjects = JSON.stringify(projects);
            localStorage.setItem('projects', serializedProjects);
        } catch (error) {
            console.error('Error saving to localStorage:', error);
        }
    }

    /**
     * Loads projects from localStorage.
     * @returns {Project[]} Array of Project instances.
     */
    static loadProjects() {
        try {
            const serializedProjects = localStorage.getItem('projects');
            if (!serializedProjects) return [];
            
            const projectsData = JSON.parse(serializedProjects);
            return projectsData.map((projectData) => {
                const project = new Project(projectData.name);
                project.todos = Array.isArray(projectData.todos) ? projectData.todos.map((todoData) => {
                    // Validate dueDate
                    if (!todoData.dueDate || isNaN(Date.parse(todoData.dueDate))) {
                        console.error(`Invalid due date for todo: ${todoData.dueDate}`);
                    }
    
                    const todo = new Todo(
                        todoData.title,
                        todoData.description,
                        todoData.dueDate,
                        todoData.priority,
                        todoData.notes,
                        todoData.id // Pass the existing ID
                    );
                    todo.completed = todoData.completed;
                    todo.subtasks = Array.isArray(todoData.subtasks) ? todoData.subtasks.map((subtaskData) => {
                        return new Todo(
                            subtaskData.title,
                            subtaskData.description,
                            subtaskData.dueDate,
                            subtaskData.priority,
                            subtaskData.notes,
                            subtaskData.id
                        );
                    })
                : [];
                todo.recurrence = todoData.recurrence || null;
                return todo;
                })
            : [];
            return project;
            });
        } catch (error) {
            console.error('Failed to load projects from localStorage:', error);
            // Optional: clean corrupted data
            localStorage.removeItem('projects');
            alert('Stored data was corrupted and has been reset.');
            // Return an empty array or default projects
            return [];
        }
    }
}

// index.js

import './style.css';
import { initializeApp } from './app.js';
import { initializeUI, setupEventListeners } from './ui.js';


function init() {
    // Initialize the application
    initializeApp();

    // Initialize UI interactions
    initializeUI();

    // Set up event listeners
    setupEventListeners();
}

// Initialize the application on DOMContentLoaded
document.addEventListener('DOMContentLoaded', init);

/* style.css */

/* CSS Variables for consistent theming */
:root {
  /* Light theme colors */
  --primary-color: #4CAF60;
  --secondary-color: #f9f9f9;
  --accent-color: #FFC107;
  --text-color: #212121;
  --background-color: #FFFFFF;
  --modal-background: rgba(0, 0, 0, 0.4);
  --button-hover-color: #218838;
  --button-bg-color: var(--primary-color);
  --button-text-color: #fff;
  --selected-project-font-weight: bold;
  --font-family: 'Roboto', Arial, Helvetica, sans-serif;
}

[data-theme="dark"] {
  --background-color: #121212;
  --text-color: #FFFFFF;
}

/* Global Box Sizing and Reset */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* Base Styles */
body {
  font-family: var(--font-family);
  background-color: #f4f4f4;
  padding: 1.25rem; /* 20px */
  color: var(--text-color);
  /* background: linear-gradient(135deg, #153677, #4e085f); */
  /* color: white; */
}

.wrapper {
  display: flex; /* Use flexbox for layout */
  flex-wrap: wrap;
}


/* Sidebar Styling */
.sidebar {
  width: 20vw;
  min-height: 100vh;
  background-color: var(--secondary-color);
  padding: 1.25rem;
  position: fixed;
  overflow-y: auto;
  transition: transform 0.3s ease;
}

.sidebar.collapsed {
  transform: translateX(-100%);
}

.sidebar-toggle {
  position: fixed;
  top: 10px;
  left: 10px;
  z-index: 1001;
}

.sidebar h2 {
  margin-top: 0;
  color: var(--text-color);
}

.sidebar ul {
  list-style-type: none;
  padding: 0;
}

.sidebar ul li {
  margin: 0.625rem 0;
}

.sidebar ul li.project-item {
  padding: 0.5rem;
  border-radius: 0.25rem;
  cursor: pointer;
  transition: background-color 0.3s ease;
  outline: none;
}

.sidebar ul li.project-item:hover,
.sidebar ul li.project-item:focus {
  background-color: var(--accent-color);
}

.sidebar ul li.project-item.selected {
  font-weight: var(--selected-project-font-weight);
  background-color: var(--accent-color);
  border-left: 4px solid --primary-color;
}

/* Main Content Styling */
#app {
  flex: 1;
  /* max-width: 600px; */
  margin-left: 22vw; /* Slightly more then sidebar width for spacing */
  /* background: linear-gradient(135deg, #153677, #4e085f); */
  padding: 1.25rem;
  border-radius: 0.625rem;
  background-color: #fff;
  min-height: 100vh;
}

h1,
h2 {
  color: var(--text-color);
  font-weight: 500;
}

/* #project-list,  */
#todo-container {
  background: #fff;
  padding: 0.625rem;
  border-radius: 0.3125rem;
  box-shadow: 0 0 0.625rem rgba(0, 0, 0, 0.1);
  margin-bottom: 1.25rem;
}

.todo-item {
  display: flex;
  /* flex-direction: column; */
  justify-content: space-between;
  align-items: center;
  padding: 0.5rem;
  border-bottom: 1px solid #ddd;
  margin-bottom: 10px;
  border-radius: 5px;
  background-color: var(--secondary-color);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.todo-item:hover {
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.2);
}

.todo-item:last-child {
  border-bottom: none;
}

.todo-item.completed .todo-info {
  text-decoration: line-through;
  color: #888;
}

/* #project-list li {
  cursor: pointer;
} */

/* #project-list li.project-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
} */

input, select {
  width: calc(100% - 20px);
  padding: 10px;
  margin-bottom: 10px;
}

button {
  /* padding: 0.625rem; */
  padding: 0.5rem 0.75rem;
  background-color: var(--button-bg-color);
  color: var(--button-text-color);
  border: none;
  border-radius: 0.3125rem;
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.2 ease;
  margin-left: 0.3125rem;
  font-weight: 500;
}

button:hover,
#project-list li:hover {
  background-color: var(--button-hover-color);
  transform: translateY(-2px);
}

button:focus,
.project-item:focus {
  outline: 3px solid var(--primary-color);
  outline-offset: 2px;
}

/* Priority Classes */
.priority-high {
  color: red;
}

.priority-medium {
  color: goldenrod;
}

.priority-low {
  color: green;
}

/* #edit-task-modal {
  background-color: white;
  padding: 20px;
  border-radius: 5px;
} */

/* Modal Styling */
.modal {
  display: none; /* Hidden by default */
  position: fixed; /* Stay in place */
  z-index: 1000; /* Sit on top */
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto; /* Enable scroll if needed */
  /* background-color: rgb(0, 0, 0);  Fallback color */
  background-color: var(--modal-background) /* Black w/ opacity */
}

.modal-content {
  opacity: 0;
  transform: translateY(-50px);
  animation: modalIn 0.3s forwards;
  background-color: #fff;
  margin: 10% auto; /* 10% from the top and centered */
  padding: 2rem;
  border: 1px solid #888;
  width: 90%; /* Could be more or less, depending on screen size */
  max-width: 31.25rem; /* 500px */
  border-radius: 0.3125rem;
  position: relative;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);

  /* @media (min-width: 600px) {
      width: 60%;
  }

  @media (min-width: 900px) {
      width: 40%;
  } */
}

.modal-content h2 {
  margin-bottom: 1rem;
}

.modal-content input,
.modal-content select {
  width: 100%;
  margin-bottom: 1rem;
  padding: 0.75rem;
  border: 1px solid #ccc;
  border-radius: 5px;
}

.modal-content button {
  margin-right: 0.5rem;
}

@keyframes modalIn {
  to {
      opacity: 1;
      transform: translateY(0);
  }
}

.close-button {
  color: #aaa;
  float: right;
  font-size: 1.75rem;
  font-weight: bold;
  cursor: pointer;
  border: none;
  background: none;
}

.close-button:hover,
.close-button:focus {
  color: black;
  text-decoration: none;
  outline: none;
  /* cursor: pointer; */
}

.edit-button,
.delete-button {
  background: none;
  border: none;
  cursor: pointer;
  margin-left: 6px;
}

.edit-button i,
.delete-button i {
  font-size: 1rem;
  color: var(--text-color);
}

/* .selected {
  font-weight: bold;
} */

/* Visually Hidden Class for Accessibility */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}


/* Animations */
.todo-item.fade-in {
  animation: fadeIn 0.5s forwards;
}

.todo-item.fade-out {
  animation: fadeOut 0.5s forwards;
}

@keyframes fadeIn {
  from { 
      opacity: 0; 
  }
  to {
      opacity: 1;
  }
}

@keyframes fadeOut {
  from {
      opacity: 1;
  }
  to {
      opacity: 0;
  }
}

/* Responsive Design */
@media (max-width: 760px) {
  .sidebar {
      width: 100%;
      height: auto;
      position: relative;
  }

  #app {
      margin-left: 0;
      max-width: 100%;
  }

  .modal-content {
      width: 95%;
  }
}

/* Scrollbar Styling for WebKit Browsers */
::-webkit-scrollbar {
  width: 8px;
}

.invalid {
  border-color: red;
}

#toast-container {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 1000;
}

.toast {
  background-color: #333;
  color: #fff;
  padding: 15px;
  margin-top: 10px;
  border-radius: 5px;
  opacity: 0;
  animation: fadeInOut 4s forwards;
}

@keyframes fadeInOut {
  0% { opacity: 0; }
  10%, 90% { opacity: 1; }
  100% { opacity: 0; }
}

.tags-container {
  margin-top: 10px;
}

.tag {
  display: inline-block;
  background-color: var(--accent-color);
  color: #fff;
  padding: 5px 10px;
  border-radius: 5px;
  margin-right: 5px;
  font-size: 0.75rem;
}

<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <!-- Meta Tags for Character Set and Responsive Design -->
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>To-Do List App</title>
    <meta name="description" content="A simple and effective to-do list application">
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="main.css">
    <!-- Include SortableJS -->
    <script src="https://cdn.jsdelivr.net/npm/sortablejs@1.14.0/Sortable.min.js"></script>
</head>
<body>
    <header>
        <button id="theme-toggle" aria-label="Toggle Dark Mode"><i class="fas fa-moon"></i></button>
    </header>
    <div class="wrapper">
        <!-- Sidebar -->
         <aside id="sidebar" class="sidebar" role="complementary" aria-label="Project Sidebar">
            <h2>Projects</h2>
            <ul id="project-list">
                <!-- Projects will be rendered here -->
            </ul>
            <div id="add-project">
                <label for="project-name" class="visually-hidden">New Project Name</label>
                <input type="text" id="project-name" placeholder="New Project Name" required aria-required="true">
                <button id="add-project-button" class="btn" tabindex="0" aria-label="Add Project">Add Project</button>
            </div>
            <button id="sidebar-toggle" aria-label="Toggle Sidebar"><i class="fas fa-bars"></i></button>
         </aside>

         <!-- Main Content -->
         <main id="app" role="main">
            <h1>To-Do List</h1>

            <div id="todo-container">
                <h2>Todos</h2>
                <!-- Todos will be rendered here -->
            </div>

            <form id="add-todo-form">
                <div id="add-todo">
                    <label for="todo-title" class="visually-hidden">Title</label>
                    <input type="text" id="todo-title" name="todo-title" placeholder="Title" required aria-required="true" autofocus>

                    <label for="todo-description" class="visually-hidden">Description</label>
                    <input type="text" id="todo-description" placeholder="Description">

                    <label for="todo-due-date" class="visually-hidden">Due Date</label>
                    <input type="date" id="todo-due-date" required aria-required="true">

                    <label for="todo-tags">Tags</label>
                    <input type="text" id="todo-tags" placeholder="Enter tags separated by commas">

                    <label for="todo-priority" class="visually-hidden">Priority</label>
                    <select id="todo-priority" aria-label="Priority">
                        <option value="low">Low</option>
                        <option value="medium">Medium</option>
                        <option value="high">High</option>
                    </select>

                    <button type="button" id="add-todo-button" class="btn" aria-label="Add Todo">Add Todo</button>
                </div>
            </form>

            <!-- Edit Task Modal -->
             <div id="edit-task-modal" class="modal" role="dialog" aria-modal="true" aria-hidden="true" aria-labelledby="edit-task-title">
                <div class="modal-content">
                    <span class="close-button" aria-label="Close Modal">&times;</span>
                    <h2 id="edit-task-title">Edit task</h2>

                    <label for="edit-title" class="visually-hidden">Title:</label>
                    <input type="text" id="edit-title" required aria-required="true">

                    <label for="edit-description" class="visually-hidden">Description:</label>
                    <input type="text" id="edit-description">

                    <label for="edit-due-date" class="visually-hidden">Due Date:</label>
                    <input type="date" id="edit-due-date">

                    <label for="edit-priority" class="visually-hidden">Priority:</label>
                    <select id="edit-priority" aria-label="Edit Priority">
                        <option value="low">Low</option>
                        <option value="medium">Medium</option>
                        <option value="high">High</option>
                    </select>

                    <button id="save-changes-button" class="btn" aria-label="Save Changes">Save changes</button>
                    <button id="cancel-button" class="btn" aria-label="Cancel Editing">Cancel</button>
                </div>
             </div>
        </main>
    </div>
    <div id="toast-container" aria-live="polite" aria-atomic="true"></div>

    <!-- <script src=".dist/bundle.js"></script> -->
    <!-- <script src="./src/app.js" defer></script> -->
    <!-- <script type="module" src="./src/index.js" defer></script> -->
     <!-- Include the bundled JavaScript file -->
     <!-- <script src="bundle.js"></script> -->
</body>
</html>