diff --git a/app.js b/app.js new file mode 100644 index 00000000..8e2e45a4 --- /dev/null +++ b/app.js @@ -0,0 +1,156 @@ +const savedData = localStorage.getItem('shoppingCart'); + +let products = savedData ? JSON.parse(savedData) : [ + {id: 1, name: "Помідори", amount: 2, isBought: true, isEditing: false}, + {id: 2, name: "Печиво", amount: 2, isBought: false, isEditing: false}, + {id: 3, name: "Сир", amount: 1, isBought: false, isEditing: false} +]; + +const productsContainer = document.getElementById("items-list"); +const leftStatsContainer = document.getElementById("remaining-container"); +const boughtStatsContainer = document.getElementById("bought-container"); +const shoppingForm = document.getElementById("shopping-form"); +const searchInput = document.getElementById("item-input"); + +function render() { + localStorage.setItem('shoppingCart', JSON.stringify(products)); + + if (!productsContainer || !leftStatsContainer || !boughtStatsContainer) return; + + productsContainer.innerHTML = ""; + leftStatsContainer.innerHTML = ""; + boughtStatsContainer.innerHTML = ""; + + products.forEach(product => { + let itemHtml = ''; + + if (product.isBought) { + itemHtml = ` +
  • + ${product.name} +
    + ${product.amount} +
    +
    + +
    +
  • + `; + boughtStatsContainer.insertAdjacentHTML('beforeend', ` + + ${product.name} ${product.amount} + + `); + } else { + let nameContent = ''; + if (product.isEditing) { + nameContent = ``; + } else { + nameContent = `${product.name}`; + } + + itemHtml = ` +
  • + ${nameContent} +
    + + ${product.amount} + +
    +
    + + +
    +
  • + `; + leftStatsContainer.insertAdjacentHTML('beforeend', ` + + ${product.name} ${product.amount} + + `); + } + + productsContainer.insertAdjacentHTML("beforeend", itemHtml); + }); +} + +if (shoppingForm) { + shoppingForm.addEventListener("submit", (event) => { + event.preventDefault(); + const newProductName = searchInput.value.trim(); + + if (newProductName) { + products.push({ + id: Date.now(), + name: newProductName, + amount: 1, + isBought: false, + isEditing: false + }); + searchInput.value = ""; + render(); + } + searchInput.focus(); + }); +} + +if (productsContainer) { + productsContainer.addEventListener("click", (event) => { + const itemContainer = event.target.closest("[data-id]"); + if (!itemContainer) return; + + const productId = Number(itemContainer.dataset.id); + + if (event.target.classList.contains("delete-btn")) { + products = products.filter(product => product.id !== productId); + render(); + return; + } + if (event.target.classList.contains("buy-btn")) { + const product = products.find(p => p.id === productId); + if (product) product.isBought = !product.isBought; + render(); + return; + } + if (event.target.classList.contains("plus")) { + const product = products.find(p => p.id === productId); + if (product) product.amount++; + render(); + return; + } + if (event.target.classList.contains("minus")) { + const product = products.find(p => p.id === productId); + if (product && product.amount > 1) product.amount--; + render(); + return; + } + if (event.target.classList.contains("item-name")) { + const product = products.find(p => p.id === productId); + if (product && !product.isBought) { + product.isEditing = true; + render(); + const input = productsContainer.querySelector(`[data-id="${productId}"] .item-input-edit`); + if (input) input.focus(); + } + } + }); + + productsContainer.addEventListener("blur", (event) => { + if (event.target.classList.contains("item-input-edit")) { + const itemContainer = event.target.closest("[data-id]"); + const productId = Number(itemContainer.dataset.id); + const product = products.find(p => p.id === productId); + + if (product) { + const newName = event.target.value.trim(); + if (newName) { + product.name = newName; + } + product.isEditing = false; + render(); + } + } + }, true); +} + +render(); \ No newline at end of file diff --git a/index.html b/index.html index 5971bf7d..3ee43eeb 100644 --- a/index.html +++ b/index.html @@ -1,16 +1,44 @@ - - + + My Page - - + + - - Apple - 4 - +
    + +
    +
    + + +
    + + +
    + + + +
    + +
    + Buy List + Created by:
    Микола Ващук
    +
    + \ No newline at end of file diff --git a/main.css b/main.css index 00bc872e..070a790d 100644 --- a/main.css +++ b/main.css @@ -1,17 +1,304 @@ -.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; +* { + box-sizing: border-box; +} + +body { + background-color: #e0e0e0; + font-family: sans-serif; + padding: 20px; +} + +.main-container { + max-width: 1100px; + margin: 0 auto; + overflow: hidden; +} + +.left-column { + width: 60%; + float: left; + background: white; + padding: 15px; + border-radius: 5px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); +} + +.sidebar { + width: 35%; + float: left; + margin-left: 5%; + background: white; + padding: 15px; + border-radius: 5px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); +} + +.stats-block h2 { + border-bottom: 1px solid #e0e0e0; + padding-bottom: 10px; + margin-top: 0; + margin-bottom: 15px; +} + +.divider { + border: none; + border-top: 1px solid #e0e0e0; + margin: 15px 0; +} + +.tag { + background-color: #e0e0e0; + display: inline-block; + height: 30px; + padding: 5px 10px; + border-radius: 5px; + margin-right: 5px; +} + +.tag-count { + background-color: orange; + color: white; + border-radius: 10px; + display: inline-block; + height: 20px; + width: 20px; + text-align: center; + font-weight: bold; +} + +.form { + border-bottom: 1px solid #ccc; + padding-bottom: 15px; + overflow: hidden; + display: flex; +} + +.form input { + flex-grow: 1; + padding: 10px; + border: 1px solid #ccc; + border-right: none; + border-radius: 5px 0 0 5px; + outline: none; + height: 40px; + margin: 0; +} + +.form button { + width: 130px; + padding: 0; + background-color: #2b8ce8; + color: white; + border: 1px solid #2b8ce8; + border-radius: 0 5px 5px 0; + font-weight: bold; + cursor: pointer; + box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.15); + height: 40px; + line-height: 38px; + margin: 0; +} + +.items-list { + list-style-type: none; + padding: 0; + margin: 0; +} + +.item-row { + padding: 15px 0; + border-bottom: 1px solid #eee; + display: flex; + align-items: center; +} + +.item-name { + width: 40%; +} + +.item-controls { + width: 30%; + text-align: center; + display: flex; + justify-content: center; + align-items: center; +} + +.item-actions { + width: 30%; +} + +.item-controls button { + width: 25px; + height: 25px; + border: none; + border-radius: 50%; + color: white; + font-weight: bold; + font-size: 14px; + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + padding: 0; +} + +.btn-minus { + background-color: #fa5c5c; +} + +.btn-plus { + background-color: #27ae60; +} + +.item-quantity { + background-color: #dbdbdb; + display: inline-block; + min-width: 25px; + height: 25px; + line-height: 25px; + text-align: center; + border-radius: 3px; + font-size: 12px; + margin: 0 5px; +} + +.btn-bought { + background: #f0f0f0; + border: 1px solid #ccc; + border-radius: 4px; + padding: 0 12px; + height: 25px; + font-size: 12px; + cursor: pointer; + display: inline-block; + box-shadow: 0 1px 2px rgba(0,0,0,0.1); +} + +.btn-delete { + background-color: #e74c3c; + border: none; + border-radius: 4px; + color: white; + padding: 0 8px; + height: 25px; + font-size: 12px; + cursor: pointer; + display: inline-block; + margin-left: 5px; +} + +.is-bought .item-name, +.tag.is-bought { + text-decoration: line-through; + color: #888; +} + +.item-edit-input { + width: 40%; + padding: 3px 5px; + font-size: 16px; + border: 1px solid #2b8ce8; + border-radius: 3px; + outline: none; + box-shadow: 0 0 4px rgba(43, 140, 232, 0.4); +} + +.item-controls button:disabled { + background-color: #fcdcdc; + color: #fa9696; + cursor: not-allowed; +} + +.badge { + position: fixed; + bottom: 0; + left: 20px; + background-color: #8b00ff; + color: white; + border-radius: 15px 15px 0 0; + padding: 15px 25px; + text-align: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + transform: translateY(65px); + transition: transform 0.4s ease, background-color 0.4s ease; + cursor: default; + z-index: 1000; +} + +.badge-title { + display: block; + font-size: 26px; + font-weight: bold; + margin-bottom: 25px; +} + +.badge-author { + display: block; + font-size: 16px; + line-height: 1.4; +} + +.badge:hover { + transform: translateY(0); + background-color: #4b0082; +} + +@media print { + .badge { + background-color: white !important; + color: #8b00ff !important; + border: 2px solid #8b00ff !important; + position: absolute !important; + bottom: 20px !important; + transform: none !important; + box-shadow: none !important; + } + .badge-title { + display: none !important; + } + .badge-author { + color: #8b00ff !important; + font-weight: bold !important; + } +} + +@media (max-width: 650px) { + .left-column, .sidebar { + width: 100% !important; + float: none !important; + margin-left: 0 !important; + margin-bottom: 20px; + } +} + +button[data-tooltip] { + position: relative; +} + +button[data-tooltip]::after { + content: attr(data-tooltip); + position: absolute; + bottom: 35px; + left: 50%; + background-color: #8b00ff; + color: white; + padding: 6px 10px; + border-radius: 20px; + font-size: 12px; + font-weight: normal; + white-space: nowrap; + opacity: 0; + visibility: hidden; + transform: translateX(-50%) translateY(10px) scale(0.7); + transition: transform 0.3s ease, opacity 0.3s ease, visibility 0.3s ease; + z-index: 999; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); + pointer-events: none; +} + +button[data-tooltip]:hover::after { + opacity: 1; + visibility: visible; + transform: translateX(-50%) translateY(0) scale(1); } \ No newline at end of file