From 40fa601bbed6976f1ec3d4e398cc883412f6890f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Gruszczy=C5=84ski?= Date: Wed, 9 Jul 2025 23:09:41 +0200 Subject: [PATCH] zmiany css i js --- app.py | 9 +-- static/css/style.css | 13 ++++ static/js/{list_share.js => clickable_row.js} | 25 -------- static/js/functions.js | 60 ++++++++++++++--- static/js/hide_list.js | 64 ------------------- static/js/live.js | 28 -------- static/js/mass_add.js | 23 +++++-- static/js/notes.js | 22 +++++++ static/js/receipt_section.js | 18 ++++++ static/js/{socket_reconnect.js => sockets.js} | 29 ++++++++- templates/admin/receipts.html | 4 +- templates/base.html | 3 +- templates/list_share.html | 4 +- 13 files changed, 162 insertions(+), 140 deletions(-) rename static/js/{list_share.js => clickable_row.js} (58%) delete mode 100644 static/js/hide_list.js create mode 100644 static/js/notes.js create mode 100644 static/js/receipt_section.js rename static/js/{socket_reconnect.js => sockets.js} (66%) diff --git a/app.py b/app.py index f4c6925..12015df 100644 --- a/app.py +++ b/app.py @@ -37,15 +37,16 @@ AUTHORIZED_COOKIE_VALUE = app.config.get('AUTHORIZED_COOKIE_VALUE', '80d31cdfe63 PROTECTED_JS_FILES = { "live.js", - "list_share.js", - "hide_list.js", - "socket_reconnect.js", + "notes.js", + "sockets.js", "product_suggestion.js", "expenses.js", "toggle_button.js", "user_management.js", "mass_add.js", - "functions.js" + "functions.js", + "clickable_row.js", + "receipt_section.js" } os.makedirs(UPLOAD_FOLDER, exist_ok=True) diff --git a/static/css/style.css b/static/css/style.css index e533ad3..cd45b25 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -237,3 +237,16 @@ input.form-control { .add-btn { margin-left: 10px; } + +.quantity-controls { + min-width: 120px; + display: flex; + align-items: center; + justify-content: flex-end; + gap: 4px; +} +.list-group-item { + display: flex; + align-items: center; + justify-content: space-between; +} diff --git a/static/js/list_share.js b/static/js/clickable_row.js similarity index 58% rename from static/js/list_share.js rename to static/js/clickable_row.js index 40d569b..a928fa5 100644 --- a/static/js/list_share.js +++ b/static/js/clickable_row.js @@ -1,31 +1,6 @@ -let currentItemId = null; - -function openNoteModal(event, itemId) { - event.stopPropagation(); - currentItemId = itemId; - // Pobierz notatkę z HTML-a, jeśli chcesz pokazywać aktualną (opcjonalnie) - const noteEl = document.querySelector(`#item-${itemId} small`); - document.getElementById('noteText').value = noteEl ? noteEl.innerText : ""; - const modal = new bootstrap.Modal(document.getElementById('noteModal')); - modal.show(); -} - -function submitNote(e) { - e.preventDefault(); - const text = document.getElementById('noteText').value; - - if (currentItemId !== null) { - socket.emit('update_note', { item_id: currentItemId, note: text }); - - const modal = bootstrap.Modal.getInstance(document.getElementById('noteModal')); - modal.hide(); - } -} - document.addEventListener("DOMContentLoaded", () => { document.querySelectorAll('.clickable-item').forEach(item => { item.addEventListener('click', function(e) { - // Jeśli klik w button (np. Notatka), nie zaznaczaj if (!e.target.closest('button') && e.target.tagName.toLowerCase() !== 'input') { const checkbox = this.querySelector('input[type="checkbox"]'); diff --git a/static/js/functions.js b/static/js/functions.js index e1ea2a7..1f56f41 100644 --- a/static/js/functions.js +++ b/static/js/functions.js @@ -103,6 +103,33 @@ function copyLink(link) { } } +/* function shareLink(link) { + if (navigator.share) { + navigator.share({ + title: 'Udostępnij moją listę', + text: 'Zobacz tę listę!', + url: link + }) + .catch((error) => { + console.error('Błąd podczas udostępniania', error); + alert('Nie udało się udostępnić linka'); + }); + } else { + copyLink(link); + } +} + +function fallbackCopy(link) { + navigator.clipboard.writeText(link).then(() => { + alert('Link skopiowany do schowka!'); + }); +} + */ + +function openList(link) { + window.open(link, '_blank'); +} + function fallbackCopyText(text) { const textarea = document.createElement('textarea'); textarea.value = text; @@ -129,6 +156,30 @@ function fallbackCopyText(text) { document.body.removeChild(textarea); } +function toggleVisibility(listId) { + fetch('/toggle_visibility/' + listId, {method: 'POST'}) + .then(response => response.json()) + .then(data => { + const shareHeader = document.getElementById('share-header'); + const shareUrlSpan = document.getElementById('share-url'); + const copyBtn = document.getElementById('copyBtn'); + const toggleBtn = document.getElementById('toggleVisibilityBtn'); + + if (data.is_public) { + shareHeader.textContent = '🔗 Udostępnij link:'; + shareUrlSpan.style.display = 'inline'; + shareUrlSpan.textContent = data.share_url; + copyBtn.disabled = false; + toggleBtn.innerHTML = '🙈 Ukryj listę'; + } else { + shareHeader.textContent = '🙈 Lista jest ukryta przed gośćmi'; + shareUrlSpan.style.display = 'none'; + copyBtn.disabled = true; + toggleBtn.innerHTML = '👁️ Udostępnij ponownie'; + } + }); +} + function showToast(message, type = 'primary') { const toastContainer = document.getElementById('toast-container'); const toast = document.createElement('div'); @@ -172,14 +223,12 @@ function updateListSmoothly(newItems) { } if (li) { - // Checkbox const checkbox = li.querySelector('input[type="checkbox"]'); if (checkbox) { checkbox.checked = item.purchased; - checkbox.disabled = false; // Zdejmij disabled jeśli było + checkbox.disabled = false; } - // Klasy li.classList.remove('bg-success', 'text-white', 'item-not-checked', 'opacity-50'); if (item.purchased) { li.classList.add('bg-success', 'text-white'); @@ -187,14 +236,12 @@ function updateListSmoothly(newItems) { li.classList.add('item-not-checked'); } - // Nazwa const nameSpan = li.querySelector(`#name-${item.id}`); const expectedName = `${item.name} ${quantityBadge}`.trim(); if (nameSpan && nameSpan.innerHTML.trim() !== expectedName) { nameSpan.innerHTML = expectedName; } - // Notatka let noteEl = li.querySelector('small'); if (item.note) { if (!noteEl) { @@ -209,12 +256,10 @@ function updateListSmoothly(newItems) { noteEl.remove(); } - // Usuń spinner jeśli był const sp = li.querySelector('.spinner-border'); if (sp) sp.remove(); } else { - // Twórz nowy element li = document.createElement('li'); li.className = `list-group-item d-flex justify-content-between align-items-center flex-wrap ${item.purchased ? 'bg-success text-white' : 'item-not-checked'}`; li.id = `item-${item.id}`; @@ -232,7 +277,6 @@ function updateListSmoothly(newItems) { fragment.appendChild(li); }); - // Wyczyść i wstaw nowy porządek itemsContainer.innerHTML = ''; itemsContainer.appendChild(fragment); diff --git a/static/js/hide_list.js b/static/js/hide_list.js deleted file mode 100644 index be3df64..0000000 --- a/static/js/hide_list.js +++ /dev/null @@ -1,64 +0,0 @@ -function toggleVisibility(listId) { - fetch('/toggle_visibility/' + listId, {method: 'POST'}) - .then(response => response.json()) - .then(data => { - const shareHeader = document.getElementById('share-header'); - const shareUrlSpan = document.getElementById('share-url'); - const copyBtn = document.getElementById('copyBtn'); - const toggleBtn = document.getElementById('toggleVisibilityBtn'); - - if (data.is_public) { - shareHeader.textContent = '🔗 Udostępnij link:'; - shareUrlSpan.style.display = 'inline'; - shareUrlSpan.textContent = data.share_url; - copyBtn.disabled = false; - toggleBtn.innerHTML = '🙈 Ukryj listę'; - } else { - shareHeader.textContent = '🙈 Lista jest ukryta przed gośćmi'; - shareUrlSpan.style.display = 'none'; - copyBtn.disabled = true; - toggleBtn.innerHTML = '👁️ Udostępnij ponownie'; - } - }); -} - -function copyLink(link) { - if (navigator.share) { - navigator.share({ - title: 'Udostępnij moją listę', - text: 'Zobacz tę listę!', - url: link - }).catch((error) => { - console.error('Błąd podczas udostępniania', error); - fallbackCopy(link); - }); - } else { - fallbackCopy(link); - } -} - -function shareLink(link) { - if (navigator.share) { - navigator.share({ - title: 'Udostępnij moją listę', - text: 'Zobacz tę listę!', - url: link - }) - .catch((error) => { - console.error('Błąd podczas udostępniania', error); - alert('Nie udało się udostępnić linka'); - }); - } else { - copyLink(link); - } -} - -function fallbackCopy(link) { - navigator.clipboard.writeText(link).then(() => { - alert('Link skopiowany do schowka!'); - }); -} - -function openList(link) { - window.open(link, '_blank'); -} \ No newline at end of file diff --git a/static/js/live.js b/static/js/live.js index 319af8a..4904934 100644 --- a/static/js/live.js +++ b/static/js/live.js @@ -202,33 +202,5 @@ function setupList(listId, username) { window.LIST_ID = listId; window.usernameForReconnect = username; - -socket.on('user_joined', function(data) { - showToast(`${data.username} dołączył do listy`, 'info'); -}); - -socket.on('user_left', function(data) { - showToast(`${data.username} opuścił listę`, 'warning'); -}); - -socket.on('user_list', function(data) { - if (data.users.length > 0) { - const userList = data.users.join(', '); - showToast(`Obecni: ${userList}`, 'info'); - } -}); - -socket.on('full_list', function(data) { - const itemsContainer = document.getElementById('items'); - const oldItems = Array.from(itemsContainer.querySelectorAll('li')); - - if (isListDifferent(oldItems, data.items)) { - updateListSmoothly(data.items); - showToast('Lista została zaktualizowana', 'info'); - } else { - updateListSmoothly(data.items); - } -}); - } diff --git a/static/js/mass_add.js b/static/js/mass_add.js index afdeee1..bcb4f16 100644 --- a/static/js/mass_add.js +++ b/static/js/mass_add.js @@ -20,19 +20,28 @@ document.addEventListener('DOMContentLoaded', function () { allproducts.forEach(name => { const li = document.createElement('li'); li.className = 'list-group-item d-flex justify-content-between align-items-center bg-dark text-light'; - li.textContent = name; if (addedProducts.has(name.toLowerCase())) { // Produkt już dodany — oznacz jako nieaktywny + const nameSpan = document.createElement('span'); + nameSpan.textContent = name; + li.appendChild(nameSpan); + li.classList.add('opacity-50'); const badge = document.createElement('span'); badge.className = 'badge bg-success ms-auto'; 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'; + qtyWrapper.className = 'd-flex align-items-center ms-2 quantity-controls'; // Minus const minusBtn = document.createElement('button'); @@ -51,7 +60,6 @@ document.addEventListener('DOMContentLoaded', function () { qty.className = 'form-control text-center p-1'; qty.classList.add('rounded'); qty.style.width = '50px'; - qty.style.flex = '0 0 auto'; qty.style.margin = '0 2px'; qty.title = 'Ilość'; @@ -64,26 +72,29 @@ document.addEventListener('DOMContentLoaded', function () { qty.value = parseInt(qty.value) + 1; }; - // Dodajemy przyciski i input do wrappera qtyWrapper.appendChild(minusBtn); qtyWrapper.appendChild(qty); qtyWrapper.appendChild(plusBtn); // Przycisk dodania const btn = document.createElement('button'); - btn.className = 'btn btn-sm btn-primary ms-2'; + btn.className = 'btn btn-sm btn-primary ms-4'; btn.textContent = '+'; btn.onclick = () => { const quantity = parseInt(qty.value) || 1; socket.emit('add_item', { list_id: LIST_ID, name: name, quantity: quantity }); }; - li.textContent = name; li.appendChild(qtyWrapper); li.appendChild(btn); } productList.appendChild(li); }); + + + + + } catch (err) { productList.innerHTML = '
  • Błąd ładowania danych
  • '; } diff --git a/static/js/notes.js b/static/js/notes.js new file mode 100644 index 0000000..3ac767c --- /dev/null +++ b/static/js/notes.js @@ -0,0 +1,22 @@ +let currentItemId = null; + +function openNoteModal(event, itemId) { + event.stopPropagation(); + currentItemId = itemId; + const noteEl = document.querySelector(`#item-${itemId} small`); + document.getElementById('noteText').value = noteEl ? noteEl.innerText : ""; + const modal = new bootstrap.Modal(document.getElementById('noteModal')); + modal.show(); +} + +function submitNote(e) { + e.preventDefault(); + const text = document.getElementById('noteText').value; + + if (currentItemId !== null) { + socket.emit('update_note', { item_id: currentItemId, note: text }); + + const modal = bootstrap.Modal.getInstance(document.getElementById('noteModal')); + modal.hide(); + } +} diff --git a/static/js/receipt_section.js b/static/js/receipt_section.js new file mode 100644 index 0000000..6681440 --- /dev/null +++ b/static/js/receipt_section.js @@ -0,0 +1,18 @@ +document.addEventListener("DOMContentLoaded", function() { + const receiptSection = document.getElementById("receiptSection"); + const toggleBtn = document.querySelector('[data-bs-target="#receiptSection"]'); + + if (!receiptSection || !toggleBtn) return; + + if (localStorage.getItem("receiptSectionOpen") === "true") { + new bootstrap.Collapse(receiptSection, { toggle: true }); + } + + receiptSection.addEventListener('shown.bs.collapse', function () { + localStorage.setItem("receiptSectionOpen", "true"); + }); + + receiptSection.addEventListener('hidden.bs.collapse', function () { + localStorage.setItem("receiptSectionOpen", "false"); + }); +}); diff --git a/static/js/socket_reconnect.js b/static/js/sockets.js similarity index 66% rename from static/js/socket_reconnect.js rename to static/js/sockets.js index 72e4d68..8b4f1e5 100644 --- a/static/js/socket_reconnect.js +++ b/static/js/sockets.js @@ -32,7 +32,7 @@ let wasReconnected = false; // flaga do kontrolowania toasta socket.on('connect', function() { if (!firstConnect) { - showToast('Połączono z serwerem! 🔄', 'info'); + //showToast('Połączono z serwerem!', 'info'); disableCheckboxes(true); wasReconnected = true; @@ -59,3 +59,30 @@ socket.on('joined_confirmation', function(data) { } }); + +socket.on('user_joined', function(data) { + showToast(`${data.username} dołączył do listy`, 'info'); +}); + +socket.on('user_left', function(data) { + showToast(`${data.username} opuścił listę`, 'warning'); +}); + +socket.on('user_list', function(data) { + if (data.users.length > 0) { + const userList = data.users.join(', '); + showToast(`Obecni: ${userList}`, 'info'); + } +}); + +socket.on('full_list', function(data) { + const itemsContainer = document.getElementById('items'); + const oldItems = Array.from(itemsContainer.querySelectorAll('li')); + + if (isListDifferent(oldItems, data.items)) { + updateListSmoothly(data.items); + showToast('Lista została zaktualizowana', 'info'); + } else { + updateListSmoothly(data.items); + } +}); \ No newline at end of file diff --git a/templates/admin/receipts.html b/templates/admin/receipts.html index fc7644d..bcb4a68 100644 --- a/templates/admin/receipts.html +++ b/templates/admin/receipts.html @@ -33,7 +33,9 @@ {% if not image_files %} -

    Brak wgranych zdjęć.

    + {% endif %} {% endblock %} diff --git a/templates/base.html b/templates/base.html index 2557e46..543be1d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -74,8 +74,7 @@ {% if request.endpoint != 'system_auth' %} - - + {% endif %} {% block scripts %}{% endblock %} diff --git a/templates/list_share.html b/templates/list_share.html index 6f29f73..051428c 100644 --- a/templates/list_share.html +++ b/templates/list_share.html @@ -113,7 +113,9 @@ {% block scripts %} - + + +