From dd1e507d0c6de929cd4a7a198a446edaa153c477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D0=B0=D1=81=D1=82=D0=B0=D1=81=D1=96=D1=8F?= <162579449+anastasiakovtoniuk@users.noreply.github.com> Date: Wed, 18 Jun 2025 15:26:29 +0300 Subject: [PATCH 1/3] hw4 --- style/index.html | 128 ++++++++++++++++++++++++++++++ style/style.css | 199 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 327 insertions(+) create mode 100644 style/index.html diff --git a/style/index.html b/style/index.html new file mode 100644 index 0000000..f8f06e8 --- /dev/null +++ b/style/index.html @@ -0,0 +1,128 @@ + + + + + + To-Do List + + + + +
+
+

To-Do List

+
+ +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+ + + + + \ No newline at end of file diff --git a/style/style.css b/style/style.css index e69de29..47ea707 100644 --- a/style/style.css +++ b/style/style.css @@ -0,0 +1,199 @@ +:root { + --primary-color: #007bff; + --primary-color-hover: #0056b3; + --high-priority: #dc3545; + --medium-priority: #fd7e14; + --low-priority: #6c757d; + + --text-color: #212529; + --text-muted: #6c757d; + --border-color: #ced4da; + --background-light: #f8f9fa; + --background-white: #ffffff; + + --border-radius-sm: 6px; + --border-radius-md: 8px; + --border-radius-lg: 12px; + + --focus-shadow: 0 0 0 0.2rem rgba(0,123,255,.25); + --default-transition: all 0.2s ease-in-out; +} + + +*, *::before, *::after { + box-sizing: border-box; +} + +body { + font-family: 'Inter', sans-serif; + background-color: var(--background-light); + color: var(--text-color); + margin: 0; + padding: 2rem; + display: flex; + justify-content: center; +} + + +.app-container { + width: 100%; + max-width: 700px; + background-color: var(--background-white); + border-radius: var(--border-radius-lg); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); + padding: 2rem; +} + +header h1 { + font-size: 2.5rem; + text-align: center; + margin-bottom: 2rem; +} + + +.add-task-form { + display: flex; + gap: 0.75rem; + margin-bottom: 1.5rem; +} + + +#newTaskInput, .select-wrapper select, .form-group input, .form-group select { + border: 1px solid var(--border-color); + border-radius: var(--border-radius-md); + font-size: 1rem; + transition: var(--default-transition); +} + +#newTaskInput:focus, .select-wrapper select:focus, .form-group input:focus, .form-group select:focus { + outline: none; + border-color: #80bdff; + box-shadow: var(--focus-shadow); +} + +#newTaskInput { + flex-grow: 1; + padding: 0.75rem 1rem; +} + +.filter-sort-controls { + display: flex; + gap: 1.5rem; + align-items: center; + margin-bottom: 1.5rem; + font-size: 0.9rem; + color: var(--text-muted); +} + +.select-wrapper select { + padding: 0.5rem; + cursor: pointer; + background-color: var(--background-white); +} + + +.add-btn, .form-actions button { + padding: 0.75rem 1.5rem; + border-radius: var(--border-radius-md); + font-size: 1rem; + font-weight: 500; + cursor: pointer; + border: 1px solid transparent; + transition: var(--default-transition); +} + +.add-btn, .save-btn { + background-color: var(--primary-color); + color: var(--background-white); +} + +.add-btn:hover, .save-btn:hover { + background-color: var(--primary-color-hover); +} + + + +.task-list { + list-style: none; + padding: 0; + margin: 0; +} + +.task-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 0; + border-bottom: 1px solid #e9ecef; +} +.task-item:last-child { border-bottom: none; } +.task-item:hover { background-color: var(--background-light); } +.task-item:hover .task-actions { opacity: 1; } + +.task-content { display: flex; align-items: center; gap: 0.75rem; } +.task-content label { cursor: pointer; } +.task-item.completed label { text-decoration: line-through; color: var(--text-muted); } + + +.task-content input[type="checkbox"] { + appearance: none; + width: 20px; + height: 20px; + border: 2px solid var(--border-color); + border-radius: 50%; + cursor: pointer; + position: relative; + transition: var(--default-transition); +} +.task-content input[type="checkbox"]:checked { + background-color: var(--primary-color); + border-color: var(--primary-color); +} +.task-content input[type="checkbox"]:checked::after { + content: '✔'; + font-size: 12px; + color: white; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.task-details { display: flex; align-items: center; gap: 1rem; color: var(--text-muted); } +.priority { font-size: 0.8rem; font-weight: 600; padding: 0.25rem 0.6rem; border-radius: 12px; color: var(--background-white); } +.priority.high { background-color: var(--high-priority); } +.priority.medium { background-color: var(--medium-priority); } +.priority.low { background-color: var(--low-priority); } + +.task-actions { display: flex; gap: 0.5rem; opacity: 0; transition: opacity 0.2s; } +.icon-btn { background: none; border: none; cursor: pointer; font-size: 1.1rem; color: var(--text-muted); } +.icon-btn:hover { color: var(--text-color); } + + +.modal-overlay { + position: fixed; + inset: 0; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; +} + +.modal-content { + background-color: var(--background-white); + padding: 2rem; + border-radius: var(--border-radius-lg); + box-shadow: 0 5px 15px rgba(0,0,0,0.3); + width: 90%; + max-width: 450px; +} + +.modal-content h2 { margin-top: 0; margin-bottom: 1.5rem; font-size: 1.75rem; } +.form-group { margin-bottom: 1.25rem; } +.form-group label { display: block; margin-bottom: 0.5rem; font-weight: 500; } +.form-group input, .form-group select { width: 100%; padding: 0.75rem; } + +.form-actions { display: flex; justify-content: flex-end; gap: 0.75rem; margin-top: 2rem; } +.cancel-btn { background-color: var(--background-light); border-color: var(--border-color); color: var(--text-color); } +.cancel-btn:hover { background-color: #e2e6ea; } \ No newline at end of file From f212179b9175f7421150ac80798e9d7d23a2fec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D0=B0=D1=81=D1=82=D0=B0=D1=81=D1=96=D1=8F?= Date: Tue, 24 Jun 2025 16:09:10 +0300 Subject: [PATCH 2/3] hw5 --- style/index.html | 2 +- style/main.js | 190 +++++++++++++++++++++++++++++++++++++++++++++++ style/tasks.json | 26 +++++++ 3 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 style/main.js create mode 100644 style/tasks.json diff --git a/style/index.html b/style/index.html index f8f06e8..c2d9e04 100644 --- a/style/index.html +++ b/style/index.html @@ -123,6 +123,6 @@ - + \ No newline at end of file diff --git a/style/main.js b/style/main.js new file mode 100644 index 0000000..4178100 --- /dev/null +++ b/style/main.js @@ -0,0 +1,190 @@ +document.addEventListener('DOMContentLoaded', () => { + const newTaskInput = document.getElementById('newTaskInput'); + const addBtn = document.querySelector('.add-btn'); + const sortBySelect = document.getElementById('sortBy'); + const filterBySelect = document.getElementById('filterBy'); + const taskList = document.querySelector('.task-list'); + + const taskModal = document.getElementById('task-modal'); + const modalTitle = document.getElementById('modal-title'); + const taskForm = document.getElementById('task-form'); + const taskTitleInput = document.getElementById('task-title-input'); + const taskDateInput = document.getElementById('task-date-input'); + const taskPrioritySelect = document.getElementById('task-priority-select'); + const cancelBtn = document.querySelector('.cancel-btn'); + + let tasks = []; + let editingTaskId = null; + + const renderTasks = () => { + taskList.innerHTML = ''; + + let tasksToRender = [...tasks]; + + const filterValue = filterBySelect.value; + if (filterValue === 'completed') { + tasksToRender = tasksToRender.filter(task => task.completed); + } else if (filterValue === 'pending') { + tasksToRender = tasksToRender.filter(task => !task.completed); + } + + const sortByValue = sortBySelect.value; + const priorityValues = { high: 3, medium: 2, low: 1 }; + + tasksToRender.sort((a, b) => { + if (a.completed !== b.completed) { + return a.completed ? 1 : -1; + } + if (sortByValue === 'date') { + return new Date(a.dueDate) - new Date(b.dueDate); + } else if (sortByValue === 'priority') { + return priorityValues[b.priority] - priorityValues[a.priority]; + } + return 0; + }); + + tasksToRender.forEach(task => { + const taskItem = document.createElement('li'); + taskItem.className = `task-item ${task.completed ? 'completed' : ''}`; + taskItem.dataset.id = task.id; + + const priorityClass = task.priority.toLowerCase(); + const formattedDate = new Date(task.dueDate).toLocaleDateString('uk-UA', { + day: 'numeric', month: 'long', year: 'numeric' + }); + + taskItem.innerHTML = ` +
+ + +
+
+ ${task.priority} + ${formattedDate} +
+ + +
+
+ `; + taskList.appendChild(taskItem); + }); + }; + + const openModal = (mode = 'add', taskId = null) => { + taskForm.reset(); + editingTaskId = taskId; + + if (mode === 'edit' && taskId) { + const task = tasks.find(t => t.id === taskId); + if (task) { + modalTitle.textContent = 'Редагувати завдання'; + taskTitleInput.value = task.title; + taskDateInput.value = task.dueDate; + taskPrioritySelect.value = task.priority; + } + } else { + modalTitle.textContent = 'Додати завдання'; + } + taskModal.style.display = 'flex'; + }; + + const closeModal = () => { + taskModal.style.display = 'none'; + editingTaskId = null; + }; + + const loadTasks = async () => { + try { + const response = await fetch('tasks.json'); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const initialTasks = await response.json(); + tasks = initialTasks.map(task => ({ ...task, id: Date.now() + Math.random() })); + } catch (error) { + console.error("Не вдалося завантажити завдання з tasks.json:", error); + tasks = []; + } + }; + + addBtn.addEventListener('click', () => { + const title = newTaskInput.value.trim(); + openModal('add'); + if (title) { + taskTitleInput.value = title; + newTaskInput.value = ''; + } + }); + + taskForm.addEventListener('submit', (e) => { + e.preventDefault(); + const title = taskTitleInput.value.trim(); + const dueDate = taskDateInput.value; + const priority = taskPrioritySelect.value; + + if (!title || !dueDate) { + alert('Заповніть назву завдання та дату.'); + return; + } + + if (editingTaskId) { + const task = tasks.find(t => t.id === editingTaskId); + if (task) { + task.title = title; + task.dueDate = dueDate; + task.priority = priority; + } + } else { + const newTask = { + id: Date.now(), + title, + dueDate, + priority, + completed: false, + }; + tasks.push(newTask); + } + + closeModal(); + renderTasks(); + }); + + cancelBtn.addEventListener('click', closeModal); + taskModal.addEventListener('click', (e) => { + if (e.target === taskModal) { + closeModal(); + } + }); + + taskList.addEventListener('click', (e) => { + const target = e.target; + const taskItem = target.closest('.task-item'); + if (!taskItem) return; + + const taskId = Number(taskItem.dataset.id); + + if (target.type === 'checkbox') { + const task = tasks.find(t => t.id === taskId); + if (task) { + task.completed = target.checked; + renderTasks(); + } + } else if (target.matches('.delete-btn')) { + tasks = tasks.filter(t => t.id !== taskId); + renderTasks(); + } else if (target.matches('.edit-btn')) { + openModal('edit', taskId); + } + }); + + sortBySelect.addEventListener('change', renderTasks); + filterBySelect.addEventListener('change', renderTasks); + + const initializeApp = async () => { + await loadTasks(); + renderTasks(); + }; + + initializeApp(); +}); \ No newline at end of file diff --git a/style/tasks.json b/style/tasks.json new file mode 100644 index 0000000..ae1320a --- /dev/null +++ b/style/tasks.json @@ -0,0 +1,26 @@ +[ + { + "title": "test1", + "dueDate": "2025-06-25", + "priority": "medium", + "completed": false + }, + { + "title": "test2", + "dueDate": "2025-06-26", + "priority": "high", + "completed": false + }, + { + "title": "test3", + "dueDate": "2025-07-01", + "priority": "low", + "completed": false + }, + { + "title": "test4", + "dueDate": "2025-06-28", + "priority": "medium", + "completed": false + } +] \ No newline at end of file From 1d9bc08f67885172e2824b4e0a7f00f65cebf175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D0=B0=D1=81=D1=82=D0=B0=D1=81=D1=96=D1=8F?= Date: Tue, 24 Jun 2025 16:09:33 +0300 Subject: [PATCH 3/3] hw5 --- index.html | 13 ------------- src/main.js | 0 2 files changed, 13 deletions(-) delete mode 100644 index.html delete mode 100644 src/main.js diff --git a/index.html b/index.html deleted file mode 100644 index 09c6dc0..0000000 --- a/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - Simple HTML Page - - - - - - - \ No newline at end of file diff --git a/src/main.js b/src/main.js deleted file mode 100644 index e69de29..0000000