From 93c9b25a625fb6c4a6a1cd3e33be0398465a08b7 Mon Sep 17 00:00:00 2001 From: S0rbex Date: Wed, 11 Jun 2025 12:24:42 +0300 Subject: [PATCH] pulling --- index.html | 60 ++++++++++++++ main.css | 202 +++++++++++++++++++++++++++++++++++++++++++++++ script.js | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 487 insertions(+) create mode 100644 main.css create mode 100644 script.js diff --git a/index.html b/index.html index e69de29..032c243 100644 --- a/index.html +++ b/index.html @@ -0,0 +1,60 @@ + + + + + Список покупок + + + + +
+
+
+ + +
+
+ Помідори + 2 + +
+
+ Печиво +
+ + 2 + + + +
+
+ +
+ + 1 + +
+ + +
+
+ +
+
Buy List
+
Created by:
Martynyshyn Vitalii
+
+ + + \ No newline at end of file diff --git a/main.css b/main.css new file mode 100644 index 0000000..e655315 --- /dev/null +++ b/main.css @@ -0,0 +1,202 @@ +@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@200..700&display=swap'); + +body { + font-family: "Oswald", sans-serif; + background: rgb(192, 155, 241); + margin: 0; + padding: 20px; +} +.container{ + display: flex; + gap: 10%; +} +.main-list, .sidebar { + background: white; + border-radius: 8px; + padding: 20px; +} +.main-list{ + flex: 2; +} +.sidebar{ + flex: 1; +} +.add-form{ + display: flex; + gap: 10px; + margin-bottom: 20px; +} +.add-form input { + flex:1; + padding: 8px; + font-size: 20px; +} +.add-form button{ + background: rgb(55, 145, 206); + color: white; + padding: 8px; + border: none; + border-radius: 4px; + cursor: pointer; +} +.item { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 10px; + padding: 10px 0; + border-top: 1px solid #ddd; + width: 100%; + box-sizing: border-box; +} +.item input { + font-size: 16px; + padding: 5px; +} +.crossed{ + text-decoration: line-through; + color: gray; +} +.counter{ + display: flex; + align-items: center; + gap: 15px; +} +.count{ + display: inline-block; + min-width: 5px; + text-align: center; +} +.plus, .minus{ + padding: 5px 10px; + font-size:16px; + border:none; + border-radius: 60%; + color:white; + cursor: pointer; +} +.green{ + background-color: green; +} +.red{ + background-color: red; +} +.status, .remove{ + padding: 5px, 10px; + border: none; + border-radius: 5px; + cursor: pointer; +} +.status{ + background: rgb(245, 226, 226); +} +.remove{ + background: red; + color: white; + font-size: 16px; +} +.sidebar h2{ + margin-top: 0; +} +.tag { + display: inline-block; + background: #f1c6c6; + color: black; + padding: 6px 12px; + margin: 5px; + display: inline-block; + border-radius: 10px; +} +.tag span { + background: orange; + color: #fff9ee; + margin-left: 6px; + padding: 2px 6px; + border-radius: 50%; +} +.badge { + position: fixed; + bottom: 0; + left: 0; + background-color: #8000cc; + color: white; + padding: 12px 24px; + font-size: 18px; + font-weight: bold; + border-top-left-radius: 12px; + border-top-right-radius: 12px; + cursor: pointer; + box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.2); + transition: all 1s ease; + overflow: hidden; + height: 50px; +} +.badge:hover { + height: 100px; + background-color: #3f00a8; +} +.author-text { + font-size: 14px; + font-weight: normal; + margin-top: 10px; + opacity: 0; + transition: opacity 4s ease; +} +.badge:hover .author-text { + opacity: 1; +} +@media print { + .badge { + background-color: white !important; + color: black !important; + border: 3px solid #8000cc; + box-shadow: none; + } + + .author-text { + opacity: 1 !important; + } + + .main-text { + display: none; + } +} +@media (max-width: 500px) { + .container { + flex-direction: column; + } + + .main-list, .sidebar { + width: 100%; + margin-bottom: 20px; + } +} +button { + position: relative; +} +button::after { + content: attr(data-tooltip); + position: absolute; + bottom: 40px; + left: 50%; + transform: translateX(-50%) scale(0.8) ; + background: #c000f0; + color: white; + padding: 6px 12px; + border-radius: 8px; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.3s ease, transform 0.3s ease; + z-index: 100; + font-size: 14px; +} +button:hover::after { + opacity: 1; + transform: translateX(-50%) scale(1); +} +.minus.disabled { + opacity: 0.5; + cursor: not-allowed; + pointer-events: none; +} \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..d9285e8 --- /dev/null +++ b/script.js @@ -0,0 +1,225 @@ +document.addEventListener('DOMContentLoaded', () => { + let items = [ + { id: 1, name: "Помідори", quantity: 2, purchased: true }, + { id: 2, name: "Печиво", quantity: 2, purchased: false }, + { id: 3, name: "Сир", quantity: 1, purchased: false } + ]; + let nextId = 4; + + const form = document.querySelector('.add-form'); + const input = form.querySelector('input'); + const itemsContainer = document.querySelector('.main-list'); + const sidebar = document.querySelector('.sidebar'); + + renderItems(); + updateStatistics(); + + form.addEventListener('submit', e => { + e.preventDefault(); + const name = input.value.trim(); + if (name) { + addItem(name); + input.value = ''; + input.focus(); + } + }); + + function addItem(name) { + items.push({ id: nextId++, name, quantity: 1, purchased: false }); + renderItems(); + updateStatistics(); + } + + function removeItem(id) { + items = items.filter(item => item.id !== id); + renderItems(); + updateStatistics(); + } + + function togglePurchased(id) { + const item = items.find(i => i.id === id); + if (item) { + item.purchased = !item.purchased; + renderItems(); + updateStatistics(); + } + } + + function updateQuantity(id, delta) { + const item = items.find(i => i.id === id); + if (item && !item.purchased) { + const newQuantity = item.quantity + delta; + if (newQuantity >= 1) { + item.quantity = newQuantity; + renderItems(); + updateStatistics(); + } + } + } + + function renderItems() { + itemsContainer.innerHTML = ''; + itemsContainer.appendChild(createAddForm()); + items.forEach(item => itemsContainer.appendChild(createItemElement(item))); + } + + function createAddForm() { + const form = document.createElement('form'); + form.className = 'add-form'; + + const input = document.createElement('input'); + input.type = 'text'; + input.placeholder = 'Назва товару'; + + const button = document.createElement('button'); + button.type = 'submit'; + button.textContent = 'Додати'; + button.setAttribute('data-tooltip', 'Додати товар'); + + form.append(input, button); + + form.addEventListener('submit', e => { + e.preventDefault(); + const name = input.value.trim(); + if (name) { + addItem(name); + input.value = ''; + input.focus(); + } + }); + + return form; + } + + function createItemElement(item) { + const itemEl = document.createElement('div'); + itemEl.className = `item${item.purchased ? ' куплено' : ''}`; + itemEl.dataset.id = item.id; + + if (item.purchased) { + const nameSpan = document.createElement('span'); + nameSpan.className = 'crossed'; + nameSpan.textContent = item.name; + + const countSpan = document.createElement('span'); + countSpan.className = 'count'; + countSpan.textContent = item.quantity; + + const statusBtn = document.createElement('button'); + statusBtn.className = 'status'; + statusBtn.textContent = 'Не куплено'; + statusBtn.setAttribute('data-tooltip', 'Зробити не купленим'); + statusBtn.addEventListener('click', () => togglePurchased(item.id)); + + itemEl.append(nameSpan, countSpan, statusBtn); + } else { + const nameSpan = document.createElement('span'); + nameSpan.className = 'editable-name'; + nameSpan.textContent = item.name; + nameSpan.addEventListener('click', () => { + const input = document.createElement('input'); + input.type = 'text'; + input.value = item.name; + input.className = 'name-edit'; + + nameSpan.replaceWith(input); + input.focus(); + + input.addEventListener('blur', () => { + const newName = input.value.trim(); + if (newName) item.name = newName; + renderItems(); + updateStatistics(); + }); + + input.addEventListener('keypress', e => { + if (e.key === 'Enter') input.blur(); + }); + }); + + const counter = document.createElement('div'); + counter.className = 'counter'; + + const minusBtn = document.createElement('button'); + minusBtn.className = `minus red${item.quantity === 1 ? ' disabled' : ''}`; + minusBtn.textContent = '-'; + minusBtn.disabled = item.quantity === 1; + minusBtn.setAttribute('data-tooltip', 'Зменшити'); + minusBtn.addEventListener('click', () => updateQuantity(item.id, -1)); + + const countSpan = document.createElement('span'); + countSpan.className = 'count'; + countSpan.textContent = item.quantity; + + const plusBtn = document.createElement('button'); + plusBtn.className = 'plus green'; + plusBtn.textContent = '+'; + plusBtn.setAttribute('data-tooltip', 'Збільшити'); + plusBtn.addEventListener('click', () => updateQuantity(item.id, 1)); + + counter.append(minusBtn, countSpan, plusBtn); + + const statusBtn = document.createElement('button'); + statusBtn.className = 'status'; + statusBtn.textContent = 'Куплено'; + statusBtn.setAttribute('data-tooltip', 'Позначити купленим'); + statusBtn.addEventListener('click', () => togglePurchased(item.id)); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'remove'; + removeBtn.textContent = 'x'; + removeBtn.setAttribute('data-tooltip', 'Прибрати'); + removeBtn.addEventListener('click', () => removeItem(item.id)); + + itemEl.append(nameSpan, counter, statusBtn, removeBtn); + } + + return itemEl; + } + + function updateStatistics() { + sidebar.innerHTML = ''; + + const pendingItems = items.filter(item => !item.purchased); + const purchasedItems = items.filter(item => item.purchased); + + const pendingTitle = document.createElement('h2'); + pendingTitle.textContent = 'Залишилось'; + sidebar.appendChild(pendingTitle); + + if (pendingItems.length) { + pendingItems.forEach(item => { + const tag = document.createElement('div'); + tag.className = 'tag'; + tag.textContent = item.name; + + const span = document.createElement('span'); + span.textContent = item.quantity; + tag.appendChild(span); + + sidebar.appendChild(tag); + }); + } else { + sidebar.appendChild(document.createElement('p')).textContent = 'Немає товарів'; + } + const purchasedTitle = document.createElement('h2'); + purchasedTitle.textContent = 'Куплено'; + sidebar.appendChild(purchasedTitle); + + if (purchasedItems.length) { + purchasedItems.forEach(item => { + const tag = document.createElement('div'); + tag.className = 'tag crossed'; + tag.textContent = item.name; + + const span = document.createElement('span'); + span.textContent = item.quantity; + tag.appendChild(span); + + sidebar.appendChild(tag); + }); + } else { + sidebar.appendChild(document.createElement('p')).textContent = 'Немає товарів'; + } + } +});