From 188b6ccc0e1b76baef32568c030771ad858f68ae Mon Sep 17 00:00:00 2001 From: alena Date: Fri, 6 Feb 2026 13:15:23 +0300 Subject: [PATCH] js_1 --- src/index.html | 27 +-------- src/main.js | 154 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 25 deletions(-) diff --git a/src/index.html b/src/index.html index b02120b..e28079f 100644 --- a/src/index.html +++ b/src/index.html @@ -9,7 +9,7 @@ -
+

To Do List

@@ -36,30 +36,7 @@ Delete All
-
    -
  • - - - -
  • -
  • - - - -
  • -
+
    diff --git a/src/main.js b/src/main.js index e69de29..d870036 100644 --- a/src/main.js +++ b/src/main.js @@ -0,0 +1,154 @@ +class Todo { + selectors = { + root: '[data-js-todo]', + newTaskForm: '[data-js-todo-new-task-form]', + newTaskInput: '[data-js-todo-new-task-input]', + searchTaskForm: '[data-js-todo-search-task-form]', + searchTaskInput: '[data-js-todo-search-task-input]', + totalTasks: '[data-js-todo-total-tasks]', + deleteAllButton: '[data-js-todo-delete-all-button]', + list: '[data-js-todo-list]', + item: '[data-js-todo-item]', + itemCheckbox: '[data-js-todo-item-checkbox]', + itemLabel: '[data-js-todo-item-label]', + itemDeleteButton: '[data-js-todo-item-delete-button]', + emptyMessage: '[data-js-todo-empty-message]', + } + + stateClasses = { + isVisible: 'is-visible', + isDisappearing: 'is-disappearing', + } + + localStorageKey = 'todo-items' + + constructor() { + this.rootElement = document.querySelector(this.selectors.root) + this.newTaskFormElement = this.rootElement.querySelector.querySelector(this.selectors.newTaskForm) + this.newTaskInputElement = this.rootElement.querySelector.querySelector(this.selectors.newTaskInput) + this.searchTaskFormElement = this.rootElement.querySelector.querySelector(this.selectors.searchTaskForm) + this.searchTaskInputElement = this.rootElement.querySelector.querySelector(this.selectors.searchTaskInput) + this.totalTasksElement = this.rootElement.querySelector.querySelector(this.selectors.totalTasks) + this.deleteAllButtonElement = this.rootElement.querySelector.querySelector(this.selectors.deleteAllButton) + this.listElement = this.rootElement.querySelector.querySelector(this.selectors.list) + this.emptyMessageElement = this.rootElement.querySelector.querySelector(this.selectors.emptyMessage) + this.state = { + items: this.getItemsFromLocalStorage(), + filteredItems: null, + searchQuery: "", + } + this.render() + } + + getItemsFromLocalStorage() { + const rawData = localStorage.getItem(this.localStorageKey) + + if (!rawData) { + return [] + } + + try { + const parsedData = JSON.parse(rawData) + + return Array.isArray(parsedData) ? parsedData : [] + + } catch { + console.error("Todo items parse error") + return [] + } + } + + saveItemsToLocalStorage() { + localStorage.setItem( + this.localStorageKey, + JSON.stringify(this.state.items) + ) + } + + render() { + this.totalTasksElement.textContent = this.state.items.length + + this.deleteAllButtonElement.classList.toggle( + this.stateClasses.isVisible, + rhis.state.items.length > 0 + ) + + const items = this.state.filteredItems ?? this.state.items + + this.listElement.innerHTML = items.map(({ id, title, isChecked }) => ` +
  • + + + +
  • + `).join('') + + const isEmptyFilteredItems = this.state.filteredItems?.length === 0 + const isEmptyItems = this.state.items.lenght === 0 + + this.emptyMessageElement.textContent = + isEmptyFilteredItems ? 'Tasks not found' + : isEmptyItems ? 'There are no tasks yet' + : '' + } + + addItem(title) { + this.state.items.push({ + id: crypto?.randomUUID() ?? Date.now().toString(), + title, + isChecked: false, + }) + this.saveItemsToLocalStorage() + this.render() + } + + deleteItem(id) { + this.state.items = this.state.items.filter((item) => item.id !== id) + this.saveItemsToLocalStorage() + this.render() + } + + toggleCheckedState(id) { + this.state.items = this.state.map((item) => { + if (item.id === id) { + return { + ...item, + isChecked: !item.isChecked, + } + } + + return item + }) + this.saveItemsToLocalStorage() + this.render() + } + + filter() { + const queryFormatted = this.state.searchQuery.toLowerCase() + + this.state.filteredItems = this.state.items.filter(({ title }) => { + const titleFormatted = title.toLowerCase() + + return titleFormatted.includes(queryFormatted) + }) + this.render() + } + + resetFilter() { + this.state.filteredItems = null + this.state.searchQuery = '' + this.render() + } + + bindEvents() { + + } +} + +new Todo() \ No newline at end of file