From 6431393baf80db5e4b5cae5f1fdc32b47f9fef63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Gruszczy=C5=84ski?= Date: Wed, 16 Jul 2025 16:13:54 +0200 Subject: [PATCH] =?UTF-8?q?porz=C4=85dkowanie=20kodu=20i=20poprawki=20js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 72 +++++++++++++++++++++++++-------------- static/js/functions.js | 19 +++++------ static/js/live.js | 5 +-- static/js/mass_add.js | 27 +++++---------- templates/list.html | 2 +- templates/list_share.html | 5 ++- 6 files changed, 71 insertions(+), 59 deletions(-) diff --git a/app.py b/app.py index 7d8498b..e036b27 100644 --- a/app.py +++ b/app.py @@ -1543,7 +1543,7 @@ def handle_disconnect(sid): @socketio.on("add_item") def handle_add_item(data): list_id = data["list_id"] - name = data["name"] + name = data["name"].strip() quantity = data.get("quantity", 1) try: @@ -1553,34 +1553,56 @@ def handle_add_item(data): except: quantity = 1 - new_item = Item( - list_id=list_id, - name=name, - quantity=quantity, - added_by=current_user.id if current_user.is_authenticated else None, - ) - db.session.add(new_item) + # Szukamy istniejącego itemu w tej liście (ignorując wielkość liter) + existing_item = Item.query.filter( + Item.list_id == list_id, + func.lower(Item.name) == name.lower(), + Item.not_purchased == False + ).first() - if not SuggestedProduct.query.filter_by(name=name).first(): - new_suggestion = SuggestedProduct(name=name) - db.session.add(new_suggestion) + if existing_item: + existing_item.quantity += quantity + db.session.commit() - db.session.commit() + emit( + "item_edited", + { + "item_id": existing_item.id, + "new_name": existing_item.name, + "new_quantity": existing_item.quantity + }, + to=str(list_id), + ) + else: + new_item = Item( + list_id=list_id, + name=name, + quantity=quantity, + added_by=current_user.id if current_user.is_authenticated else None, + ) + db.session.add(new_item) - emit( - "item_added", - { - "id": new_item.id, - "name": new_item.name, - "quantity": new_item.quantity, - "added_by": ( - current_user.username if current_user.is_authenticated else "Gość" - ), - }, - to=str(list_id), - include_self=True, - ) + if not SuggestedProduct.query.filter(func.lower(SuggestedProduct.name) == name.lower()).first(): + new_suggestion = SuggestedProduct(name=name) + db.session.add(new_suggestion) + db.session.commit() + + emit( + "item_added", + { + "id": new_item.id, + "name": new_item.name, + "quantity": new_item.quantity, + "added_by": ( + current_user.username if current_user.is_authenticated else "Gość" + ), + }, + to=str(list_id), + include_self=True, + ) + + # Aktualizacja postępu purchased_count, total_count, percent = get_progress(list_id) emit( diff --git a/static/js/functions.js b/static/js/functions.js index 533a179..ac36d16 100644 --- a/static/js/functions.js +++ b/static/js/functions.js @@ -217,7 +217,7 @@ function applyHidePurchased(isInit = false) { } function toggleVisibility(listId) { - fetch('/toggle_visibility/' + listId, {method: 'POST'}) + fetch('/toggle_visibility/' + listId, { method: 'POST' }) .then(response => response.json()) .then(data => { const shareHeader = document.getElementById('share-header'); @@ -297,10 +297,9 @@ function updateListSmoothly(newItems) { } // Klasy tła - li.className = `list-group-item d-flex justify-content-between align-items-center flex-wrap clickable-item ${ - item.purchased ? 'bg-success text-white' : + li.className = `list-group-item d-flex justify-content-between align-items-center flex-wrap clickable-item ${item.purchased ? 'bg-success text-white' : item.not_purchased ? 'bg-warning text-dark' : 'item-not-checked' - }`; + }`; // HTML wewnętrzny li.innerHTML = ` @@ -317,7 +316,7 @@ function updateListSmoothly(newItems) {
${item.not_purchased ? ` - @@ -334,11 +333,11 @@ function updateListSmoothly(newItems) { ` : ''} `} ${!window.IS_SHARE ? ` - - @@ -358,7 +357,7 @@ function updateListSmoothly(newItems) { } -document.addEventListener("DOMContentLoaded", function() { +document.addEventListener("DOMContentLoaded", function () { const receiptSection = document.getElementById("receiptSection"); const toggleBtn = document.querySelector('[data-bs-target="#receiptSection"]'); @@ -377,14 +376,14 @@ document.addEventListener("DOMContentLoaded", function() { }); }); -document.addEventListener("DOMContentLoaded", function() { +document.addEventListener("DOMContentLoaded", function () { const toggle = document.getElementById('hidePurchasedToggle'); if (!toggle) return; const savedState = localStorage.getItem('hidePurchasedToggle'); toggle.checked = savedState === 'true'; applyHidePurchased(true); - toggle.addEventListener('change', function() { + toggle.addEventListener('change', function () { localStorage.setItem('hidePurchasedToggle', toggle.checked ? 'true' : 'false'); applyHidePurchased(); }); diff --git a/static/js/live.js b/static/js/live.js index d48ae68..9cc05c3 100644 --- a/static/js/live.js +++ b/static/js/live.js @@ -144,11 +144,11 @@ function setupList(listId, username) { ${data.name} ${quantityBadge}
- - @@ -156,6 +156,7 @@ function setupList(listId, username) { `; document.getElementById('items').prepend(li); + toggleEmptyPlaceholder(); }); socket.on('item_deleted', data => { diff --git a/static/js/mass_add.js b/static/js/mass_add.js index 0265f35..495517e 100644 --- a/static/js/mass_add.js +++ b/static/js/mass_add.js @@ -2,11 +2,16 @@ document.addEventListener('DOMContentLoaded', function () { const modal = document.getElementById('massAddModal'); const productList = document.getElementById('mass-add-list'); + // Funkcja normalizacji (usuwa diakrytyki i zamienia na lowercase) + function normalize(str) { + return str.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase(); + } + modal.addEventListener('show.bs.modal', async function () { let addedProducts = new Set(); document.querySelectorAll('#items li').forEach(li => { if (li.dataset.name) { - addedProducts.add(li.dataset.name.toLowerCase()); + addedProducts.add(normalize(li.dataset.name)); } }); @@ -20,8 +25,7 @@ document.addEventListener('DOMContentLoaded', function () { const li = document.createElement('li'); li.className = 'list-group-item d-flex justify-content-between align-items-center bg-dark text-light'; - if (addedProducts.has(name.toLowerCase())) { - // Produkt już dodany — oznacz jako nieaktywny + if (addedProducts.has(normalize(name))) { const nameSpan = document.createElement('span'); nameSpan.textContent = name; li.appendChild(nameSpan); @@ -32,17 +36,14 @@ document.addEventListener('DOMContentLoaded', function () { badge.textContent = 'Dodano'; li.appendChild(badge); } else { - // Nazwa produktu const nameSpan = document.createElement('span'); nameSpan.textContent = name; nameSpan.style.flex = '1 1 auto'; li.appendChild(nameSpan); - // Kontener na minus, pole i plus const qtyWrapper = document.createElement('div'); qtyWrapper.className = 'd-flex align-items-center ms-2 quantity-controls'; - // Minus const minusBtn = document.createElement('button'); minusBtn.type = 'button'; minusBtn.className = 'btn btn-outline-light btn-sm px-2'; @@ -51,18 +52,15 @@ document.addEventListener('DOMContentLoaded', function () { qty.value = Math.max(1, parseInt(qty.value) - 1); }; - // Pole ilości const qty = document.createElement('input'); qty.type = 'number'; qty.min = 1; qty.value = 1; - qty.className = 'form-control text-center p-1'; - qty.classList.add('rounded'); + qty.className = 'form-control text-center p-1 rounded'; qty.style.width = '50px'; qty.style.margin = '0 2px'; qty.title = 'Ilość'; - // Plus const plusBtn = document.createElement('button'); plusBtn.type = 'button'; plusBtn.className = 'btn btn-outline-light btn-sm px-2'; @@ -75,7 +73,6 @@ document.addEventListener('DOMContentLoaded', function () { qtyWrapper.appendChild(qty); qtyWrapper.appendChild(plusBtn); - // Przycisk dodania const btn = document.createElement('button'); btn.className = 'btn btn-sm btn-primary ms-4'; btn.textContent = '+'; @@ -99,25 +96,19 @@ document.addEventListener('DOMContentLoaded', function () { document.querySelectorAll('#mass-add-list li').forEach(li => { const itemName = li.firstChild.textContent.trim(); - if (itemName === data.name && !li.classList.contains('opacity-50')) { - // Usuń wszystkie dzieci + if (normalize(itemName) === normalize(data.name) && !li.classList.contains('opacity-50')) { while (li.firstChild) { li.removeChild(li.firstChild); } - // Ustaw nazwę li.textContent = data.name; - - // Dodaj klasę wyszarzenia li.classList.add('opacity-50'); - // Dodaj badge const badge = document.createElement('span'); badge.className = 'badge bg-success ms-auto'; badge.textContent = 'Dodano'; li.appendChild(badge); - // Zablokuj kliknięcia li.onclick = null; } }); diff --git a/templates/list.html b/templates/list.html index 9f3c548..6c76190 100644 --- a/templates/list.html +++ b/templates/list.html @@ -84,7 +84,7 @@
-