diff --git a/index.html b/index.html
index 5971bf7d..3752d31f 100644
--- a/index.html
+++ b/index.html
@@ -1,16 +1,75 @@
-
-
+
+
- My Page
-
-
+
+ Кошик покупок
-
- Apple
- 4
-
+
+
+
+
+
+
+
+
+
+
+
Помідори
+
+ 2
+
+
+
+
+
+
Печиво
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
Залишилося
+
+ Печиво 2
+ Сир 1
+
+
+
+
+
Куплено
+
+ Помідори 2
+
+
+
+
+
+
+ Buy List
+ Виконано: Мартинов Богдан
+
+
\ No newline at end of file
diff --git a/main.css b/main.css
index 00bc872e..758ab52f 100644
--- a/main.css
+++ b/main.css
@@ -1,17 +1,397 @@
-.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;
+ margin: 0;
+ padding: 0;
+ font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+}
+
+body
+{
+ background-color: #e5e5e5;
+ min-height: 100vh;
+ padding: 40px 20px;
+}
+
+
+.app-container
+{
+ max-width: 1000px;
+ margin: 0 auto;
+ display: flex;
+ gap: 24px;
+ align-items: flex-start;
+}
+
+.products-section
+{
+ flex: 2;
+ background: #ffffff;
+ border-radius: 8px;
+ padding: 16px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
+}
+
+.summary-section
+{
+ flex: 1;
+}
+
+.summary-card
+{
+ background: #ffffff;
+ border-radius: 8px;
+ padding: 20px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
+}
+
+
+.add-item-box
+{
+ display: flex;
+ gap: 12px;
+ border-bottom: 2px solid #f0f0f0;
+ padding-bottom: 16px;
+ margin-bottom: 8px;
+}
+
+.input-field, .input-edit
+{
+ flex: 1;
+ padding: 10px 14px;
+ border: 1px solid #dcdcdc;
+ border-radius: 4px;
+ font-size: 16px;
+ outline: none;
+}
+
+.input-edit
+{
+ border-color: #4285f4;
+ max-width: 200px;
+}
+
+.input-field:focus, .input-edit:focus
+{
+ border-color: #4285f4;
+ box-shadow: 0 0 0 2px rgba(66, 133, 244, 0.2);
+}
+
+
+button
+{
+ cursor: pointer;
+ border: none;
+ outline: none;
+ font-size: 14px;
+ transition: background-color 0.2s ease, transform 0.1s ease;
+}
+
+button:focus-visible
+{
+ outline: 3px solid #7b2cbf;
+ outline-offset: 2px;
+}
+
+.btn-add
+{
+ background-color: #4285f4;
+ color: white;
+ padding: 10px 24px;
+ border-radius: 4px;
+ font-weight: bold;
+}
+
+.btn-add:hover { background-color: #357ae8; }
+
+
+.products-list
+{
+ display: flex;
+ flex-direction: column;
+}
+
+.product-row
+{
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 12px 0;
+ border-bottom: 1px solid #f0f0f0;
+}
+
+.product-row:last-child
+{
+ border-bottom: none;
+}
+
+.product-name
+{
+ font-size: 18px;
+ color: #333;
+}
+
+
+
+
+.controls
+{
+ display: grid;
+ grid-template-columns: 28px 28px 28px 100px 28px;
+ gap: 8px;
+ align-items: center;
+ justify-items: center;
+}
+
+.amount-badge
+{
+ background-color: #e0e0e0;
+ color: #333;
+ width: 28px;
+ height: 28px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 4px;
+ font-weight: bold;
+ font-size: 14px;
+}
+
+.btn-plus, .btn-minus
+{
+ width: 28px;
+ height: 28px;
+ border-radius: 50%;
+ color: white;
+ font-weight: bold;
+ font-size: 16px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+
+.btn-plus { background-color: #22ba46; }
+.btn-plus:hover { background-color: #1e9e3b; }
+
+
+.btn-minus { background-color: #db2828; }
+.btn-minus:hover { background-color: #b82222; }
+
+
+.btn-minus.disabled
+{
+ background-color: #ef9f9e;
+ cursor: not-allowed;
+}
+
+.btn-status
+{
+ width: 100%;
+ background-color: #eeeeee;
+ color: #444;
+ padding: 6px 0;
+ border-radius: 4px;
+ border: 1px solid #dcdcdc;
+ text-align: center;
+}
+.btn-status:hover { background-color: #e0e0e0; }
+
+.btn-status.active
+{
+ background-color: #f8f9fa;
+ box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
+}
+
+.btn-delete
+{
+ background-color: #db2828;
+ color: white;
+ width: 28px;
+ height: 28px;
+ border-radius: 4px;
+ font-size: 18px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.btn-delete:hover { background-color: #b82222; }
+
+
+.summary-card h2
+{
+ font-size: 20px;
+ margin-bottom: 14px;
+ color: #111;
+}
+
+.summary-divider
+{
+ border: none;
+ border-top: 1px solid #f0f0f0;
+ margin: 20px 0;
+}
+
+.summary-tags
+{
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.product-tag
+{
+ background-color: #eeeeee;
+ padding: 6px 12px;
+ border-radius: 20px;
+ font-size: 14px;
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ color: #444;
+}
+
+.product-tag.bought
+{
+ text-decoration: line-through;
+ color: #888;
+}
+
+
+.tag-count {
+ background-color: #f2711d;
+ color: white;
+ width: 18px;
+ height: 18px;
+ border-radius: 50%;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 11px;
+ font-weight: bold;
+}
+
+
+[data-tooltip]
+{
+ position: relative;
+}
+
+[data-tooltip]::after
+{
+ content: attr(data-tooltip);
+ position: absolute;
+ bottom: 100%;
+ left: 50%;
+ transform: translate(-50%, 8px) scale(0.6);
+ opacity: 0;
+ pointer-events: none;
+ transition: transform 0.25s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.2s ease;
+
+ background-color: #7b2cbf;
+ color: #ffffff;
+ padding: 6px 12px;
+ border-radius: 6px;
+ font-size: 12px;
+ font-weight: normal;
+ white-space: nowrap;
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
+ margin-bottom: 8px;
+ z-index: 999;
+}
+
+[data-tooltip]:hover::after,
+[data-tooltip]:focus-visible::after
+{
+ opacity: 1;
+ transform: translate(-50%, 0) scale(1);
+}
+
+
+
+.author-badge
+{
+ position: fixed;
+ bottom: 0;
+ left: 40px;
+ background-color: #5a189a;
+ color: #ffffff;
+ padding: 12px 24px;
+ border-radius: 12px 12px 0 0;
+ font-weight: bold;
+ font-size: 16px;
+ box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.15);
+ z-index: 1000;
+ cursor: default;
+
+ height: 45px;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ transition: height 0.3s ease, background-color 0.3s ease;
+}
+
+.badge-text-author
+{
+ font-weight: normal;
+ font-size: 13px;
+ opacity: 0.9;
+}
+
+.author-badge:hover, .author-badge:focus-within
+{
+ height: 75px;
+ background-color: #3c096c;
+}
+
+
+@media (max-width: 650px)
+{
+ body
+ {
+ padding: 16px 10px;
+ }
+
+ .app-container
+ {
+ flex-direction: column;
+ gap: 16px;
+ }
+
+ .products-section, .summary-section
+ {
+ width: 100%;
+ flex: none;
+ }
+}
+
+
+@media print
+{
+ .author-badge
+ {
+ position: absolute;
+ bottom: 20px;
+ left: 20px;
+ background: #ffffff;
+ color: #5a189a;
+ border: 2px solid #5a189a;
+ height: auto;
+ padding: 8px 16px;
+ border-radius: 8px;
+ box-shadow: none;
+ }
+
+ .badge-text-main
+ {
+ display: none;
+ }
+
+ .badge-text-author
+ {
+ display: block;
+ font-size: 16px;
+ font-weight: bold;
+ }
}
\ No newline at end of file
diff --git a/main.js b/main.js
new file mode 100644
index 00000000..cb9fd28f
--- /dev/null
+++ b/main.js
@@ -0,0 +1,222 @@
+document.addEventListener('DOMContentLoaded', () => {
+ let products = [
+ { id: 1, name: 'Помідори', amount: 2, isBought: true },
+ { id: 2, name: 'Печиво', amount: 2, isBought: false },
+ { id: 3, name: 'Сир', amount: 1, isBought: false }
+ ];
+
+ let nextId = 4;
+
+ const productsListElement = document.querySelector('.products-list');
+ const inputField = document.querySelector('.input-field');
+ const btnAdd = document.querySelector('.btn-add');
+ const summaryTagsContainers = document.querySelectorAll('.summary-tags');
+
+ function renderList()
+ {
+ productsListElement.innerHTML = '';
+
+ products.forEach(product => {
+ productsListElement.appendChild(createProductRow(product));
+ });
+
+ updateSummary();
+ }
+
+ function createProductRow(product)
+ {
+ const row = document.createElement('div');
+ row.className = `product-row ${product.isBought ? 'bought' : ''}`;
+
+
+ const nameSpan = document.createElement('span');
+ nameSpan.className = 'product-name';
+ nameSpan.textContent = product.name;
+
+ const nameInput = document.createElement('input');
+ nameInput.type = 'text';
+ nameInput.className = 'input-edit';
+ nameInput.setAttribute('aria-label', 'Редагувати назву товару');
+
+ if (!product.isBought)
+ {
+ nameSpan.style.cursor = 'pointer';
+
+ nameSpan.addEventListener('click', () => {
+ row.replaceChild(nameInput, nameSpan);
+ nameInput.value = product.name;
+ nameInput.focus();
+ });
+
+ const saveEdit = () => {
+ const newName = nameInput.value.trim();
+ if (newName)
+ {
+ product.name = newName;
+ }
+ nameSpan.textContent = product.name;
+
+ if (nameInput.parentNode === row)
+ {
+ row.replaceChild(nameSpan, nameInput);
+ }
+ updateSummary();
+ };
+
+ nameInput.addEventListener('blur', saveEdit);
+ nameInput.addEventListener('keypress', (e) => {
+ if (e.key === 'Enter') saveEdit();
+ });
+ }
+
+ row.appendChild(nameSpan);
+
+ const controls = document.createElement('div');
+ controls.className = 'controls';
+
+ if (product.isBought)
+ {
+ const amountBadge = document.createElement('span');
+ amountBadge.className = 'amount-badge';
+ amountBadge.style.gridColumn = '2';
+ amountBadge.textContent = product.amount;
+
+ const btnStatus = document.createElement('button');
+ btnStatus.type = 'button';
+ btnStatus.className = 'btn-status';
+ btnStatus.style.gridColumn = '4';
+ btnStatus.setAttribute('data-tooltip', 'Повернути в список залишившихся');
+ btnStatus.textContent = 'Не куплено';
+
+ btnStatus.addEventListener('click', () => {
+ product.isBought = false;
+ renderList();
+ });
+
+ controls.appendChild(amountBadge);
+ controls.appendChild(btnStatus);
+ }
+ else
+ {
+ const btnMinus = document.createElement('button');
+ btnMinus.type = 'button';
+ btnMinus.className = `btn-minus ${product.amount === 1 ? 'disabled' : ''}`;
+ if (product.amount === 1)
+ {
+ btnMinus.disabled = true;
+ }
+ btnMinus.setAttribute('aria-label', 'Зменшити кількість');
+ btnMinus.setAttribute('data-tooltip', 'Мінімум 1');
+ btnMinus.textContent = '-';
+ btnMinus.addEventListener('click', () => {
+ if (product.amount > 1)
+ {
+ product.amount--;
+ renderList();
+ }
+ });
+
+ const amountBadge = document.createElement('span');
+ amountBadge.className = 'amount-badge';
+ amountBadge.textContent = product.amount;
+
+ const btnPlus = document.createElement('button');
+ btnPlus.type = 'button';
+ btnPlus.className = 'btn-plus';
+ btnPlus.setAttribute('aria-label', 'Збільшити кількість');
+ btnPlus.setAttribute('data-tooltip', 'Збільшити');
+ btnPlus.textContent = '+';
+ btnPlus.addEventListener('click', () => {
+ product.amount++;
+ renderList();
+ });
+
+ const btnStatus = document.createElement('button');
+ btnStatus.type = 'button';
+ btnStatus.className = 'btn-status active';
+ btnStatus.setAttribute('data-tooltip', 'Позначити як куплене');
+ btnStatus.textContent = 'Куплено';
+ btnStatus.addEventListener('click', () => {
+ product.isBought = true;
+ renderList();
+ });
+
+ const btnDelete = document.createElement('button');
+ btnDelete.type = 'button';
+ btnDelete.className = 'btn-delete';
+ btnDelete.setAttribute('aria-label', 'Видалити товар');
+ btnDelete.setAttribute('data-tooltip', 'Видалити зі списку');
+ btnDelete.textContent = '×';
+ btnDelete.addEventListener('click', () => {
+ products = products.filter(p => p.id !== product.id);
+ renderList();
+ });
+
+ controls.appendChild(btnMinus);
+ controls.appendChild(amountBadge);
+ controls.appendChild(btnPlus);
+ controls.appendChild(btnStatus);
+ controls.appendChild(btnDelete);
+ }
+
+ row.appendChild(controls);
+ return row;
+ }
+
+ function updateSummary() {
+ const leftContainer = summaryTagsContainers[0];
+ const rightContainer = summaryTagsContainers[1];
+
+ leftContainer.innerHTML = '';
+ rightContainer.innerHTML = '';
+
+ products.forEach(product => {
+ const tag = document.createElement('span');
+ tag.className = `product-tag ${product.isBought ? 'bought' : ''}`;
+
+ tag.appendChild(document.createTextNode(product.name + ' '));
+
+ const countSpan = document.createElement('span');
+ countSpan.className = 'tag-count';
+ countSpan.textContent = product.amount;
+
+ tag.appendChild(countSpan);
+
+ if (product.isBought)
+ {
+ rightContainer.appendChild(tag);
+ }
+ else
+ {
+ leftContainer.appendChild(tag);
+ }
+ });
+ }
+
+ function handleAddProduct()
+ {
+ const name = inputField.value.trim();
+ if (name)
+ {
+ products.push({
+ id: nextId++,
+ name: name,
+ amount: 1,
+ isBought: false
+ });
+ inputField.value = '';
+ inputField.focus();
+ renderList();
+ }
+ }
+
+ btnAdd.addEventListener('click', handleAddProduct);
+ inputField.addEventListener('keypress', (e) => {
+ if (e.key === 'Enter')
+ {
+ handleAddProduct();
+ }
+ });
+
+ renderList();
+});
\ No newline at end of file