zmiany ux i nowe funckje
This commit is contained in:
@@ -32,6 +32,16 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* rodzic już ma position-relative */
|
||||
.progress-label {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
pointer-events: none; /* klikalne przyciski obok paska nie ucierpią */
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.progress-thin {
|
||||
height: 12px;
|
||||
}
|
||||
@@ -250,3 +260,8 @@ input.form-control {
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#empty-placeholder {
|
||||
font-style: italic;
|
||||
pointer-events: none;
|
||||
}
|
@@ -281,6 +281,7 @@ function updateListSmoothly(newItems) {
|
||||
itemsContainer.appendChild(fragment);
|
||||
|
||||
updateProgressBar();
|
||||
toggleEmptyPlaceholder();
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
|
@@ -1,5 +1,25 @@
|
||||
const socket = io();
|
||||
|
||||
/*──────────────── placeholder pustej listy ────────────────*/
|
||||
function toggleEmptyPlaceholder() {
|
||||
const list = document.getElementById('items');
|
||||
if (!list) return;
|
||||
|
||||
// prawdziwe <li> to te z data‑name lub id="item‑…"
|
||||
const hasRealItems = list.querySelector('li[data-name], li[id^="item-"]') !== null;
|
||||
const placeholder = document.getElementById('empty-placeholder');
|
||||
|
||||
if (!hasRealItems && !placeholder) {
|
||||
const li = document.createElement('li');
|
||||
li.id = 'empty-placeholder';
|
||||
li.className = 'list-group-item bg-dark text-secondary text-center w-100';
|
||||
li.textContent = 'Brak produktów w tej liście.';
|
||||
list.appendChild(li);
|
||||
} else if (hasRealItems && placeholder) {
|
||||
placeholder.remove();
|
||||
}
|
||||
}
|
||||
|
||||
function setupList(listId, username) {
|
||||
socket.emit('join_list', { room: listId, username: username });
|
||||
|
||||
@@ -135,6 +155,7 @@ function setupList(listId, username) {
|
||||
|
||||
document.getElementById('items').appendChild(li);
|
||||
updateProgressBar();
|
||||
toggleEmptyPlaceholder();
|
||||
});
|
||||
|
||||
socket.on('item_deleted', data => {
|
||||
@@ -144,6 +165,7 @@ function setupList(listId, username) {
|
||||
}
|
||||
showToast('Usunięto produkt');
|
||||
updateProgressBar();
|
||||
toggleEmptyPlaceholder();
|
||||
});
|
||||
|
||||
socket.on('progress_updated', function(data) {
|
||||
@@ -197,10 +219,10 @@ function setupList(listId, username) {
|
||||
});
|
||||
|
||||
updateProgressBar();
|
||||
toggleEmptyPlaceholder();
|
||||
|
||||
// --- WAŻNE: zapisz dane do reconnect ---
|
||||
window.LIST_ID = listId;
|
||||
window.usernameForReconnect = username;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -3,7 +3,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
const productList = document.getElementById('mass-add-list');
|
||||
|
||||
modal.addEventListener('show.bs.modal', async function () {
|
||||
// 🔥 Za każdym razem od nowa budujemy zbiór produktów już na liście
|
||||
let addedProducts = new Set();
|
||||
document.querySelectorAll('#items li').forEach(li => {
|
||||
if (li.dataset.name) {
|
||||
@@ -91,16 +90,11 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
productList.appendChild(li);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} catch (err) {
|
||||
productList.innerHTML = '<li class="list-group-item text-danger bg-dark">Błąd ładowania danych</li>';
|
||||
}
|
||||
});
|
||||
|
||||
// 🔥 Aktualizacja na żywo po dodaniu
|
||||
socket.on('item_added', data => {
|
||||
document.querySelectorAll('#mass-add-list li').forEach(li => {
|
||||
const itemName = li.firstChild.textContent.trim();
|
||||
|
85
static/js/receipt_upload.js
Normal file
85
static/js/receipt_upload.js
Normal file
@@ -0,0 +1,85 @@
|
||||
let receiptToastShown = false;
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const form = document.getElementById("receiptForm");
|
||||
const input = document.getElementById("receiptInput");
|
||||
const gallery = document.getElementById("receiptGallery");
|
||||
const progressContainer = document.getElementById("progressContainer");
|
||||
const progressBar = document.getElementById("progressBar");
|
||||
|
||||
if (!form || !input || !gallery) return;
|
||||
|
||||
form.addEventListener("submit", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const file = input.files[0];
|
||||
if (!file) {
|
||||
showToast("Nie wybrano pliku!", "warning");
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("receipt", file);
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", form.action, true);
|
||||
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||
|
||||
xhr.upload.onprogress = function (e) {
|
||||
if (e.lengthComputable) {
|
||||
const percent = Math.round((e.loaded / e.total) * 100);
|
||||
progressBar.style.width = percent + "%";
|
||||
progressBar.textContent = percent + "%";
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onloadstart = function () {
|
||||
progressContainer.style.display = "block";
|
||||
progressBar.style.width = "0%";
|
||||
progressBar.textContent = "0%";
|
||||
};
|
||||
|
||||
xhr.onloadend = function () {
|
||||
progressContainer.style.display = "none";
|
||||
progressBar.style.width = "0%";
|
||||
progressBar.textContent = "";
|
||||
input.value = "";
|
||||
};
|
||||
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
if (xhr.status === 200) {
|
||||
const res = JSON.parse(xhr.responseText);
|
||||
if (res.success && res.url) {
|
||||
|
||||
fetch(window.location.href)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(html, "text/html");
|
||||
const newGallery = doc.getElementById("receiptGallery");
|
||||
if (newGallery) {
|
||||
gallery.innerHTML = newGallery.innerHTML;
|
||||
|
||||
if (!receiptToastShown) {
|
||||
showToast("Wgrano paragon", "success");
|
||||
receiptToastShown = true;
|
||||
}
|
||||
socket.emit("receipt_uploaded", {
|
||||
list_id: LIST_ID,
|
||||
url: res.url
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
showToast(res.message || "Błąd podczas wgrywania.", "danger");
|
||||
}
|
||||
} else {
|
||||
showToast("Błąd serwera. Spróbuj ponownie.", "danger");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(formData);
|
||||
});
|
||||
});
|
@@ -1,3 +1,5 @@
|
||||
let didReceiveFirstFullList = false;
|
||||
|
||||
// --- Automatyczny reconnect po powrocie do karty/przywróceniu internetu ---
|
||||
function reconnectIfNeeded() {
|
||||
if (!socket.connected) {
|
||||
@@ -75,14 +77,45 @@ socket.on('user_list', function(data) {
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('full_list', function(data) {
|
||||
const itemsContainer = document.getElementById('items');
|
||||
const oldItems = Array.from(itemsContainer.querySelectorAll('li'));
|
||||
socket.on('receipt_added', function (data) {
|
||||
const gallery = document.getElementById("receiptGallery");
|
||||
if (!gallery) return;
|
||||
|
||||
if (isListDifferent(oldItems, data.items)) {
|
||||
updateListSmoothly(data.items);
|
||||
showToast('Lista została zaktualizowana', 'info');
|
||||
} else {
|
||||
updateListSmoothly(data.items);
|
||||
// Usuń placeholder, jeśli istnieje
|
||||
const alert = gallery.querySelector(".alert");
|
||||
if (alert) {
|
||||
alert.remove();
|
||||
}
|
||||
|
||||
// Sprawdź, czy już istnieje obraz z tym URL
|
||||
const existing = Array.from(gallery.querySelectorAll("img")).find(img => img.src === data.url);
|
||||
if (!existing) {
|
||||
const col = document.createElement("div");
|
||||
col.className = "col-6 col-md-4 col-lg-3 text-center";
|
||||
col.innerHTML = `
|
||||
<a href="${data.url}" data-lightbox="receipt" data-title="Paragon">
|
||||
<img src="${data.url}" class="img-fluid rounded shadow-sm border border-secondary" style="max-height: 200px; object-fit: cover;">
|
||||
</a>
|
||||
`;
|
||||
gallery.appendChild(col);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
socket.on('full_list', function (data) {
|
||||
const itemsContainer = document.getElementById('items');
|
||||
|
||||
const oldItems = Array.from(
|
||||
itemsContainer.querySelectorAll('li[data-name], li[id^="item-"]')
|
||||
);
|
||||
|
||||
const isDifferent = isListDifferent(oldItems, data.items);
|
||||
|
||||
updateListSmoothly(data.items);
|
||||
toggleEmptyPlaceholder();
|
||||
|
||||
if (didReceiveFirstFullList && isDifferent) {
|
||||
showToast('Lista została zaktualizowana', 'info');
|
||||
}
|
||||
didReceiveFirstFullList = true;
|
||||
});
|
Reference in New Issue
Block a user