diff --git a/index.html b/index.html
index 5971bf7d..47c5dc25 100644
--- a/index.html
+++ b/index.html
@@ -1,16 +1,80 @@
-
-
+
+
- My Page
-
-
+ Buy List
-
- Apple
- 4
-
+
+
+
+
+
+
+
+
+ -
+ Помідори
+
+ 2
+
+
+
+
+
+
+ -
+ Печиво
+
+
+ 2
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
Залишилося
+
+ Печиво 2
+ Сир 1
+
+
+
+
+
Куплено
+
+ Помідори 2
+
+
+
+
+
+
+ Buy List
+ Created by:
Vadim Dudar
+
+
+
-
\ No newline at end of file
+
diff --git a/main.css b/main.css
index 00bc872e..8d45fdf9 100644
--- a/main.css
+++ b/main.css
@@ -1,17 +1,315 @@
-.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 {
+ background-color: #e0e0e0;
+ font-family: Arial, sans-serif;
+ margin: 0;
+ padding: 20px;
+ display: flex;
+ justify-content: center;
+}
+
+.container {
+ display: flex;
+ gap: 20px;
+ max-width: 1000px;
+ width: 100%;
+}
+
+.left-panel {
+ background-color: white;
+ flex: 2;
+ border-radius: 4px;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+ padding: 20px;
+}
+
+.add-item-container {
+ display: flex;
+ margin-bottom: 20px;
+ border-bottom: 1px solid #eee;
+ padding-bottom: 20px;
+}
+
+.add-input {
+ flex: 1;
+ padding: 10px;
+ border: 1px solid #ccc;
+ border-radius: 4px 0 0 4px;
+ font-size: 16px;
+ outline: none;
+}
+
+.add-button {
+ background-color: #3b78c4;
+ color: white;
+ border: none;
+ padding: 10px 20px;
+ font-size: 16px;
+ font-weight: bold;
+ border-radius: 0 4px 4px 0;
+ cursor: pointer;
+}
+
+.items-list {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.item-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 15px 0;
+ border-bottom: 1px solid #eee;
+}
+
+.item-row:last-child {
+ border-bottom: none;
+}
+
+.item-title {
+ flex: 1;
+ font-size: 18px;
+}
+
+.item-title-edit {
+ flex: 1;
+ font-size: 18px;
+ padding: 5px;
+ margin-right: 15px;
+ border: 1px solid #3b78c4;
+ border-radius: 4px;
+ outline: none;
+}
+
+.crossed-out {
+ text-decoration: line-through;
+ color: #888;
+}
+
+.quantity-controls {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ width: 120px;
+ justify-content: center;
+}
+
+.qty-btn {
+ width: 32px;
+ height: 32px;
+ border: none;
+ border-radius: 50%;
+ color: white;
+ font-weight: bold;
+ font-size: 18px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.qty-btn.minus {
+ background-color: #c9302c;
+}
+
+.qty-btn.minus.faded {
+ background-color: #e59a98;
+ cursor: not-allowed;
+}
+
+.qty-btn.plus {
+ background-color: #4cae4c;
+}
+
+.quantity-value {
+ background-color: #e0e0e0;
+ padding: 5px 12px;
+ border-radius: 4px;
+ font-weight: bold;
+}
+
+/* Кнопки дій */
+.action-buttons {
+ display: flex;
+ gap: 5px;
+ width: 140px;
+ justify-content: flex-end;
+}
+
+.status-btn {
+ padding: 8px 12px;
+ background-color: #f0f0f0;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ cursor: pointer;
+ font-weight: bold;
+ color: #555;
+}
+
+.delete-btn {
+ background-color: #c9302c;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ padding: 8px 12px;
+ cursor: pointer;
+ font-weight: bold;
+}
+
+.right-panel {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+}
+
+.stats-card {
+ background-color: white;
+ border-radius: 4px;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+ padding: 20px;
+}
+
+.stats-card h2 {
+ margin-top: 0;
+ font-size: 20px;
+ border-bottom: 1px solid #eee;
+ padding-bottom: 15px;
+ margin-bottom: 15px;
+}
+
+.stats-items-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+
+.stat-badge {
+ background-color: #e6e6e6;
+ padding: 5px 10px;
+ border-radius: 4px;
+ font-size: 14px;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.stat-qty {
+ background-color: #e67e22;
+ color: white;
+ border-radius: 50%;
+ width: 20px;
+ height: 20px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 12px;
+ font-weight: bold;
+}
+
+[data-tooltip] {
+ position: relative;
+}
+
+[data-tooltip]::after {
+ content: attr(data-tooltip);
+ position: absolute;
+ bottom: calc(100% + 6px);
+ left: 50%;
+ transform: translateX(-50%) scale(0);
+ transform-origin: bottom center;
+ background-color: #6a0dad;
+ color: white;
+ padding: 6px 12px;
+ border-radius: 6px;
+ font-size: 13px;
+ font-weight: normal;
+ white-space: nowrap;
+ opacity: 0;
+ pointer-events: none;
+ transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.25s ease;
+ z-index: 100;
+ box-shadow: 0 2px 6px rgba(0,0,0,0.2);
+}
+
+[data-tooltip]:hover::after {
+ opacity: 1;
+ transform: translateX(-50%) scale(1);
+}
+
+@media screen and (max-width: 650px) {
+ .container {
+ flex-direction: column;
+ }
+}
+
+.author-badge {
+ position: fixed;
+ bottom: 0;
+ left: 20px;
+ transform: translateY(calc(100% - 45px));
+ background-color: #9c00d4;
+ color: white;
+ padding: 10px 20px;
+ border-radius: 12px 12px 0 0;
+ transition: transform 0.4s ease, background-color 0.4s ease;
+ text-align: center;
+ z-index: 1000;
+ box-shadow: 0 -2px 10px rgba(0,0,0,0.15);
+ font-family: Arial, sans-serif;
+}
+
+.badge-title {
+ display: block;
+ font-size: 22px;
+ font-weight: bold;
+ line-height: 25px;
+ margin-bottom: 20px;
+}
+
+.badge-author {
+ display: block;
+ font-size: 15px;
+ line-height: 1.4;
+ padding-bottom: 5px;
+}
+
+.author-badge:hover {
+ transform: translateY(0);
+ background-color: #3b00bd;
+}
+
+@media print {
+ body {
+ background-color: white !important;
+ }
+
+ [data-tooltip]::after {
+ display: none !important;
+ }
+
+ .author-badge {
+ position: static;
+ transform: translateY(0);
+ background-color: white !important;
+ color: #4a148c !important;
+ border: 2px solid #4a148c !important;
+ border-radius: 6px !important;
+ padding: 15px;
+ box-shadow: none;
+ display: inline-block;
+ margin-top: 30px;
+ }
+
+ .badge-title {
+ display: none;
+ }
+
+ .badge-author {
+ color: #4a148c !important;
+ margin: 0;
+ padding: 0;
+ font-weight: bold;
+ }
+}
diff --git a/main.js b/main.js
new file mode 100644
index 00000000..9746888f
--- /dev/null
+++ b/main.js
@@ -0,0 +1,191 @@
+document.addEventListener('DOMContentLoaded', () => {
+ const STATE_KEY = 'buyListState';
+
+ let items = [];
+
+ const defaultItems = [
+ { id: 1, name: 'Помідори', quantity: 2, isBought: true },
+ { id: 2, name: 'Печиво', quantity: 2, isBought: false },
+ { id: 3, name: 'Сир', quantity: 1, isBought: false }
+ ];
+
+ const savedState = localStorage.getItem(STATE_KEY);
+ if (savedState) {
+ try {
+ items = JSON.parse(savedState);
+ } catch (e) {
+ items = [...defaultItems];
+ }
+ } else {
+ items = [...defaultItems];
+ }
+
+ const generateId = () => {
+ return items.length > 0 ? Math.max(...items.map(i => i.id)) + 1 : 1;
+ };
+
+ const saveState = () => {
+ localStorage.setItem(STATE_KEY, JSON.stringify(items));
+ };
+
+ const addInput = document.querySelector('.add-input');
+ const addButton = document.querySelector('.add-button');
+ const itemsList = document.querySelector('.items-list');
+ const statsUnbought = document.querySelectorAll('.stats-items-list')[0];
+ const statsBought = document.querySelectorAll('.stats-items-list')[1];
+
+ const render = () => {
+ itemsList.innerHTML = '';
+ statsUnbought.innerHTML = '';
+ statsBought.innerHTML = '';
+
+ items.forEach(item => {
+ const li = document.createElement('li');
+ li.className = 'item-row';
+
+ if (item.isBought) {
+ li.innerHTML = `
+ ${escapeHtml(item.name)}
+
+ ${item.quantity}
+
+
+
+
+ `;
+ } else {
+ li.innerHTML = `
+ ${escapeHtml(item.name)}
+
+
+ ${item.quantity}
+
+
+
+
+
+
+ `;
+ }
+
+ const unbuyBtn = li.querySelector('.unbuy-btn');
+ if (unbuyBtn) unbuyBtn.addEventListener('click', () => toggleStatus(item.id));
+
+ const buyBtn = li.querySelector('.buy-btn');
+ if (buyBtn) buyBtn.addEventListener('click', () => toggleStatus(item.id));
+
+ const deleteBtn = li.querySelector('.delete-btn');
+ if (deleteBtn) deleteBtn.addEventListener('click', () => deleteItem(item.id));
+
+ const plusBtn = li.querySelector('.plus');
+ if (plusBtn) plusBtn.addEventListener('click', () => changeQuantity(item.id, 1));
+
+ const minusBtn = li.querySelector('.minus');
+ if (minusBtn) minusBtn.addEventListener('click', () => changeQuantity(item.id, -1));
+
+ const titleSpan = li.querySelector('.item-title:not(.crossed-out)');
+ if (titleSpan) {
+ titleSpan.addEventListener('click', () => {
+ const input = document.createElement('input');
+ input.type = 'text';
+ input.className = 'item-title-edit';
+ input.value = item.name;
+
+ const saveEdit = () => {
+ const newName = input.value.trim();
+ if (newName) {
+ editName(item.id, newName);
+ } else {
+ render();
+ }
+ };
+
+ input.addEventListener('blur', saveEdit);
+ input.addEventListener('keypress', (e) => {
+ if (e.key === 'Enter') {
+ input.blur();
+ }
+ });
+
+ li.replaceChild(input, titleSpan);
+ input.focus();
+ input.select();
+ });
+ }
+
+ itemsList.appendChild(li);
+
+ const statBadge = document.createElement('span');
+ statBadge.className = 'stat-badge' + (item.isBought ? ' crossed-out' : '');
+ statBadge.innerHTML = `${escapeHtml(item.name)} ${item.quantity}`;
+
+ if (item.isBought) {
+ statsBought.appendChild(statBadge);
+ } else {
+ statsUnbought.appendChild(statBadge);
+ }
+ });
+
+ saveState();
+ };
+
+ const escapeHtml = (unsafe) => {
+ return unsafe.replace(/&/g, "&").replace(//g, ">");
+ }
+
+ const addItem = () => {
+ const name = addInput.value.trim();
+ if (name) {
+ items.push({
+ id: generateId(),
+ name: name,
+ quantity: 1,
+ isBought: false
+ });
+ addInput.value = '';
+ addInput.focus();
+ render();
+ }
+ };
+
+ const deleteItem = (id) => {
+ items = items.filter(item => item.id !== id);
+ render();
+ };
+
+ const toggleStatus = (id) => {
+ const item = items.find(item => item.id === id);
+ if (item) {
+ item.isBought = !item.isBought;
+ render();
+ }
+ };
+
+ const changeQuantity = (id, delta) => {
+ const item = items.find(item => item.id === id);
+ if (item) {
+ const newQty = item.quantity + delta;
+ if (newQty >= 1) {
+ item.quantity = newQty;
+ render();
+ }
+ }
+ };
+
+ const editName = (id, newName) => {
+ const item = items.find(item => item.id === id);
+ if (item) {
+ item.name = newName;
+ render();
+ }
+ };
+
+ addButton.addEventListener('click', addItem);
+ addInput.addEventListener('keypress', (e) => {
+ if (e.key === 'Enter') {
+ addItem();
+ }
+ });
+
+ render();
+});