From b9b91ff82b7e0feeccbb673154e09e69e6585d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Gruszczy=C5=84ski?= Date: Mon, 28 Jul 2025 00:04:12 +0200 Subject: [PATCH] duzo poprawek ux i logicznych --- app.py | 2 ++ static/js/functions.js | 14 +++++---- static/js/live.js | 56 ++++++++++++++++------------------- static/js/receipt_section.js | 21 +++++++++++++ templates/admin/receipts.html | 10 +++---- templates/list.html | 2 ++ templates/list_share.html | 7 ++--- 7 files changed, 68 insertions(+), 44 deletions(-) diff --git a/app.py b/app.py index 6ede434..2862eee 100644 --- a/app.py +++ b/app.py @@ -1147,6 +1147,7 @@ def view_list(list_id): total_count = len(items) purchased_count = len([i for i in items if i.purchased]) percent = (purchased_count / total_count * 100) if total_count > 0 else 0 + is_owner = current_user.id == shopping_list.owner_id return render_template( "list.html", @@ -1159,6 +1160,7 @@ def view_list(list_id): expenses=expenses, total_expense=total_expense, is_share=False, + is_owner=is_owner ) diff --git a/static/js/functions.js b/static/js/functions.js index 1154a86..e344aaf 100644 --- a/static/js/functions.js +++ b/static/js/functions.js @@ -281,6 +281,9 @@ function renderItem(item, isShare = window.IS_SHARE, showEditOnly = false) { : 'item-not-checked' }`; + const isOwner = window.IS_OWNER === true || window.IS_OWNER === 'true'; + const allowEdit = !isShare || showEditOnly || isOwner; + let quantityBadge = ''; if (item.quantity && item.quantity > 1) { quantityBadge = `x${item.quantity}`; @@ -309,8 +312,8 @@ function renderItem(item, isShare = window.IS_SHARE, showEditOnly = false) { let rightButtons = ''; - // ✏️ i 🗑️ — tylko jeśli nie jesteśmy w trybie /share lub jesteśmy w 15s (tymczasowo) - if (!isShare || showEditOnly) { + // ✏️ i 🗑️ — tylko jeśli nie jesteśmy w trybie /share lub jesteśmy w 15s (tymczasowo) lub jesteśmy właścicielem + if (allowEdit) { rightButtons += ` `; } - li.innerHTML = `${left}
${rightButtons}
`; if (item.added_by && item.owner_id && item.added_by_id && item.added_by_id !== item.owner_id) { diff --git a/static/js/live.js b/static/js/live.js index 4f13c51..ee4654b 100644 --- a/static/js/live.js +++ b/static/js/live.js @@ -205,43 +205,39 @@ function setupList(listId, username) { }); socket.on('note_updated', data => { - const itemEl = document.getElementById(`item-${data.item_id}`); - if (itemEl) { - let noteEl = itemEl.querySelector('small'); - if (noteEl) { - //noteEl.innerHTML = `[ Notatka: ${data.note} ]`; - noteEl.innerHTML = `[ ${data.note} ]`; - } else { - const newNote = document.createElement('small'); - newNote.className = 'text-danger ms-4'; - //newNote.innerHTML = `[ Notatka: ${data.note} ]`; - newNote.innerHTML = `[ ${data.note} ]`; + const idx = window.currentItems.findIndex(i => i.id === data.item_id); + if (idx !== -1) { + window.currentItems[idx].note = data.note; - const flexColumn = itemEl.querySelector('.d-flex.flex-column'); - if (flexColumn) { - flexColumn.appendChild(newNote); - } else { - itemEl.appendChild(newNote); - } + const newItem = renderItem(window.currentItems[idx], true); + const oldItem = document.getElementById(`item-${data.item_id}`); + if (oldItem && newItem) { + oldItem.replaceWith(newItem); } } + showToast('Notatka dodana/zaktualizowana', 'success'); }); - socket.on('item_edited', data => { - const nameSpan = document.getElementById(`name-${data.item_id}`); - if (nameSpan) { - let quantityBadge = ''; - if (data.new_quantity && data.new_quantity > 1) { - quantityBadge = ` x${data.new_quantity}`; - } - nameSpan.innerHTML = `${data.new_name}${quantityBadge}`; - } - showToast(`Zaktualizowano produkt: ${data.new_name} (x${data.new_quantity})`, 'success'); - }); - updateProgressBar(); - toggleEmptyPlaceholder(); + socket.on('item_edited', data => { + const idx = window.currentItems.findIndex(i => i.id === data.item_id); + if (idx !== -1) { + window.currentItems[idx].name = data.new_name; + window.currentItems[idx].quantity = data.new_quantity; + + const newItem = renderItem(window.currentItems[idx], true); + const oldItem = document.getElementById(`item-${data.item_id}`); + if (oldItem && newItem) { + oldItem.replaceWith(newItem); + } + } + + showToast(`Zaktualizowano produkt: ${data.new_name} (x${data.new_quantity})`, 'success'); + + updateProgressBar(); + toggleEmptyPlaceholder(); + }); // --- WAŻNE: zapisz dane do reconnect --- window.LIST_ID = listId; diff --git a/static/js/receipt_section.js b/static/js/receipt_section.js index 9f474e9..6a8b271 100644 --- a/static/js/receipt_section.js +++ b/static/js/receipt_section.js @@ -16,3 +16,24 @@ document.addEventListener("DOMContentLoaded", function () { localStorage.setItem("receiptSectionOpen", "false"); }); }); + +document.addEventListener("DOMContentLoaded", function () { + const btn = document.getElementById("toggleReceiptBtn"); + const target = document.querySelector(btn.getAttribute("data-bs-target")); + + function updateUI() { + const isShown = target.classList.contains("show"); + btn.innerHTML = isShown + ? "📄 Ukryj sekcję paragonów" + : "📄 Pokaż sekcję paragonów"; + + btn.classList.toggle("active", isShown); + btn.classList.toggle("btn-outline-light", !isShown); + btn.classList.toggle("btn-secondary", isShown); + } + + target.addEventListener("shown.bs.collapse", updateUI); + target.addEventListener("hidden.bs.collapse", updateUI); + + updateUI(); +}); \ No newline at end of file diff --git a/templates/admin/receipts.html b/templates/admin/receipts.html index a7affee..475f18c 100644 --- a/templates/admin/receipts.html +++ b/templates/admin/receipts.html @@ -65,15 +65,17 @@ {% if orphan_files and request.path.endswith('/all') %} -

Znalezione nieprzypisane pliki ({{ orphan_files_count }})

{% for f in orphan_files %}
- + + +

{{ f }}

Brak powiązania z listą!
@@ -88,8 +90,6 @@
{% endif %} - -