diff --git a/index.html b/index.html index 5971bf7..4b24ebd 100644 --- a/index.html +++ b/index.html @@ -1,16 +1,27 @@ - - - - My Page + + + BuyList + + + + + + +
+
+
+
+ + +
+
+
+
+
+
BuyList
+ + - - - - - - Apple - 4 - - - \ No newline at end of file diff --git a/main.css b/main.css index 00bc872..0fecd7e 100644 --- a/main.css +++ b/main.css @@ -1,17 +1,312 @@ -.product-item { - background-color: gray; - display: inline-block; - height: 25px; - padding: 5px; - border-radius: 5px; -} - -.amount { - background-color: yellow; - border-radius: 10px; - - display: inline-block; - height: 20px; - width: 20px; - text-align: center; -} \ No newline at end of file +body { + font-family: Arial, sans-serif; + background: #f9f9f9; + margin: 0; + padding: 20px; +} + +.container { + display: flex; + flex-wrap: wrap; + gap: 20px; + align-items: flex-start; +} + +.left, .right { + background: white; + padding: 20px; + border-radius: 12px; + box-shadow: 0 0 8px rgba(0,0,0,0.1); + flex: 1 1 300px; + min-width: 300px; + +} + +.left-container { + display: flex; + align-items: center; + justify-content: center; + width: 100% +} + +form { + display: flex; + margin-bottom: 20px; + flex-wrap: wrap; + gap: 10px; +} + +input[type="text"] { + max-width: 175px; + padding: 10px; + flex: 1; + font-size: 16px; + border: 1px solid #ccc; + border-radius: 8px; +} + + +.item input:focus { + border-color: #0056b3; /* Темніша блакитна при фокусі */ + box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25); /* Світла тінь */ +} + +.add-btn { + background-color: #007bff; + color: white; + border: none; + padding: 10px 20px; + border-radius: 8px; + position: relative; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.add-btn:hover { + background-color: #0056b3; +} + +.item { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 15px; + flex-wrap: wrap; + border-bottom: 1px solid #eee; + padding-bottom: 10px; +} + +.item > div { + width: 33%; + position: relative; + +} + +.item input { + padding: 8px 12px; + border: 2px solid #007bff; + border-radius: 8px; + font-size: 16px; + outline: none; + width:50%; +} + + +.delete-buttons { + display: flex; + flex-wrap: wrap; + justify-content: flex-end; + gap: 8px; + flex: 1; + min-width: 120px; +} + +.item-name { + flex: 1; + font-size: 16px; + word-break: break-word; + white-space: normal; + min-width: 0; +} + + +.item-name.bought { + text-decoration: line-through; + color: #c8c4c4; +} +.bought { + text-decoration: line-through; + color: #000000; +} + +.controls { + display: flex; + align-items: center; + justify-content: center; + gap: 10px; + flex: 1; + min-width: 100px; + width: 120px; + margin: 5px auto; +} + +.controls > * { + flex: 1; + flex-grow: 0; +} + +.controls button { + padding: 6px 12px; + border-radius: 50%; + font-size: 18px; + border: none; + color: white; + position: relative; + cursor: pointer; + transition: background-color 0.3s ease; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; +} + +.controls button.plus { + background-color: #28a745; +} + +.controls button.minus { + background-color: #dc3545; +} + +.status-btn { + padding: 6px 12px; + border-radius: 8px; + border: 1px solid #ccc; + background-color: #eee; + margin-left: 10px; + position: relative; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.status-btn:hover { + background-color: #ddd; +} + +.delete { + background-color: #f44336; + color: white; + padding: 6px 12px; + border-radius: 8px; + margin-left: 10px; + position: relative; + cursor: pointer; + transition: background-color 0.3s ease; + border: none; + font-size: 18px; + display: flex; + align-items: center; + justify-content: center; +} + +.delete:hover { + background-color: #d32f2f; +} + +.right h3 { + margin-bottom: 10px; + margin-top: 20px; + padding-bottom: 10px; + border-bottom: 1px solid #eee; +} + +.tag { + display: inline-block; + background-color: #aeadab; + color: rgb(0, 0, 0); + padding: 6px 10px; + border-radius: 8px; + margin: 4px; + font-size: 14px; +} + +.badge { + background: #e77f10; + color: #ffffff; + padding: 2px 6px; + border-radius: 8px; + margin-left: 5px; +} + +.badge-bottom { + position: fixed; + bottom: 0; + left: 20px; + background-color: #4b2e83; + color: white; + padding: 12px 24px; + border-radius: 12px 12px 0 0; + font-weight: bold; + font-size: 18px; + box-shadow: 0 4px 10px rgba(75, 46, 131, 0.5); + transition: background-color 0.3s ease, transform 0.4s cubic-bezier(.4,2,.6,1); + cursor: pointer; + z-index: 1000; + border: none; +} + +.badge-bottom:hover { + background-color: #6a3fc8; + transform: translateY(-10px); +} + +.badge-bottom:hover::after { + content: "Робота Котульська Нонна"; + display: block; + font-size: 14px; + margin-top: 4px; +} + +button[data-tooltip]:hover::after, +.add-btn[data-tooltip]:hover::after { + content: attr(data-tooltip); + position: absolute; + background: #4b2e83; + color: white; + padding: 6px 10px; + border-radius: 8px; + bottom: -35px; + left: 50%; + transform: translateX(-50%) scale(1); + opacity: 1; + transition: opacity 0.3s, transform 0.3s; + white-space: nowrap; + pointer-events: none; + z-index: 10; +} + +button[data-tooltip]::after, +.add-btn[data-tooltip]::after { + content: ""; + opacity: 0; + transform: scale(0.8); + transition: opacity 0.3s, transform 0.3s; + position: absolute; +} + +@media screen and (max-width: 1000px) { + .container { + flex-direction: column; + } + + .container > div { + width: 90%; + } +} + +@media screen and (max-width: 404px) { + .item > div { + width: 25%; + } +} + +@media print { + .badge-bottom { + background-color: white !important; + color: transparent !important; + border: 2px solid #4b2e83 !important; + box-shadow: none !important; + transform: none !important; + position: static !important; + margin-bottom: 10px; + } + + .badge-bottom::after { + content: "Котульська Нонна" !important; + color: #4b2e83 !important; + opacity: 1 !important; + display: block; + margin-top: 4px; + } +} diff --git a/main.js b/main.js new file mode 100644 index 0000000..4b3f647 --- /dev/null +++ b/main.js @@ -0,0 +1,214 @@ +document.addEventListener('DOMContentLoaded', () => { + const form = document.querySelector('form'); + const input = form.querySelector('input[type="text"]'); + const itemsContainer = document.querySelector('.left'); + const itemsList = document.createElement('div'); + itemsList.id = 'items-list'; + itemsContainer.appendChild(itemsList); + + const rightPanel = document.querySelector('.right'); + let leftStats = rightPanel.querySelector('.left-stats'); + let boughtStats = rightPanel.querySelector('.bought-stats'); + + if (!leftStats) { + const h3Left = document.createElement('h3'); + h3Left.textContent = 'Залишилося'; + rightPanel.appendChild(h3Left); + leftStats = document.createElement('div'); + leftStats.className = 'left-stats'; + rightPanel.appendChild(leftStats); + } + + if (!boughtStats) { + const h3Bought = document.createElement('h3'); + h3Bought.textContent = 'Куплено'; + rightPanel.appendChild(h3Bought); + boughtStats = document.createElement('div'); + boughtStats.className = 'bought-stats'; + rightPanel.appendChild(boughtStats); + } + + function loadItemsFromDOM() { + const items = []; + const itemElements = document.querySelectorAll('.left .item'); + itemElements.forEach(itemEl => { + const nameEl = itemEl.querySelector('.item-name, input.item-input'); + const quantityEl = itemEl.querySelector('.quantity'); + const statusBtn = itemEl.querySelector('.status-btn'); + + const name = nameEl ? (nameEl.value || nameEl.textContent).trim() : ''; + const quantity = quantityEl ? parseInt(quantityEl.textContent) || 1 : 1; + const bought = statusBtn ? statusBtn.textContent.toLowerCase().includes('куплено') : false; + + if (name) { + items.push({ name, quantity, bought }); + } + }); + return items; + } + + let items = JSON.parse(localStorage.getItem('buylist')); + if (!items || !items.length) { + items = loadItemsFromDOM(); + if (!items.length) { + items = [ + { name: 'Помідори', quantity: 2, bought: true }, + { name: 'Печиво', quantity: 2, bought: false }, + { name: 'Сир', quantity: 1, bought: false }, + ]; + } + } + + function save() { + localStorage.setItem('buylist', JSON.stringify(items)); + } + + function createNameElement(item, index) { + const nameDiv = document.createElement('div'); + nameDiv.className = 'item-name' + (item.bought ? ' bought' : ''); + nameDiv.textContent = item.name; + if (!item.bought) { + nameDiv.style.cursor = 'pointer'; + nameDiv.addEventListener('click', () => { + const input = document.createElement('input'); + input.type = 'text'; + input.value = item.name; + input.className = 'item-input'; + nameDiv.replaceWith(input); + input.focus(); + + function saveName() { + const newName = input.value.trim(); + if (newName) { + item.name = newName; + } + save(); + render(); + updateStats(); + } + + input.addEventListener('blur', saveName); + input.addEventListener('keydown', e => { + if (e.key === 'Enter') { + input.blur(); + } + }); + }); + } + return nameDiv; + } + + function render() { + itemsList.innerHTML = ''; + items.forEach((item, index) => { + const itemDiv = document.createElement('div'); + itemDiv.className = 'item'; + + const nameElem = createNameElement(item, index); + itemDiv.appendChild(nameElem); + + const controls = document.createElement('div'); + controls.className = 'controls'; + + if (!item.bought) { + const minusBtn = document.createElement('button'); + minusBtn.className = 'minus'; + minusBtn.setAttribute('data-tooltip', 'Зменшити кількість'); + minusBtn.textContent = '−'; + minusBtn.disabled = item.quantity <= 1; + minusBtn.addEventListener('click', () => { + if (item.quantity > 1) { + item.quantity--; + save(); + qtySpan.textContent = item.quantity; + // render(); + updateStats(); + } + }); + controls.appendChild(minusBtn); + } + + const qtySpan = document.createElement('span'); + qtySpan.className = 'quantity'; + qtySpan.textContent = item.quantity; + controls.appendChild(qtySpan); + + if (!item.bought) { + const plusBtn = document.createElement('button'); + plusBtn.className = 'plus'; + plusBtn.setAttribute('data-tooltip', 'Збільшити кількість'); + plusBtn.textContent = '+'; + plusBtn.addEventListener('click', () => { + item.quantity++; + save(); + qtySpan.textContent = item.quantity; + // render(); + updateStats(); + }); + controls.appendChild(plusBtn); + } + itemDiv.appendChild(controls); + + const btnsDiv = document.createElement('div'); + btnsDiv.className = 'delete-buttons'; + + const statusBtn = document.createElement('button'); + statusBtn.className = 'status-btn'; + statusBtn.setAttribute('data-tooltip', 'Змінити статус'); + statusBtn.textContent = item.bought ? 'Не куплено' : 'Куплено'; + statusBtn.addEventListener('click', () => { + item.bought = !item.bought; + save(); + render(); + updateStats(); + }); + btnsDiv.appendChild(statusBtn); + + if (!item.bought) { + const delBtn = document.createElement('button'); + delBtn.className = 'delete'; + delBtn.setAttribute('data-tooltip', 'Видалити'); + delBtn.textContent = '✖'; + delBtn.addEventListener('click', () => { + items.splice(index, 1); + save(); + render(); + updateStats(); + }); + btnsDiv.appendChild(delBtn); + } + + itemDiv.appendChild(btnsDiv); + itemsList.appendChild(itemDiv); + }); + updateStats(); + } + + function updateStats() { + leftStats.innerHTML = ''; + boughtStats.innerHTML = ''; + items.forEach(item => { + const tag = document.createElement('div'); + tag.className = 'tag'; + tag.innerHTML = `${item.name} ${item.quantity}`; + if (item.bought) boughtStats.appendChild(tag); + else leftStats.appendChild(tag); + }); + } + + form.addEventListener('submit', e => { + e.preventDefault(); + const name = input.value.trim(); + if (name) { + items.push({ name, quantity: 1, bought: false }); + save(); + render(); + updateStats(); + input.value = ''; + input.focus(); + } + }); + + render(); + updateStats(); +}); \ No newline at end of file