154 lines
5.5 KiB
JavaScript
154 lines
5.5 KiB
JavaScript
(function () {
|
||
const tbody = document.querySelector('#produkty-body');
|
||
const celInput = document.querySelector('#cel');
|
||
const box = document.querySelector('#celSyncBox');
|
||
const msg = document.querySelector('#celSyncMsg');
|
||
const btn = document.querySelector('#btnApplyCelFromSum');
|
||
|
||
if (!tbody || !celInput || !box || !msg || !btn) return;
|
||
|
||
const EPS = 0.01; // tolerancja porównania
|
||
|
||
function parsePrice(raw) {
|
||
if (!raw) return NaN;
|
||
const s = String(raw).trim().replace(/\s+/g, '').replace(',', '.');
|
||
const n = Number(s);
|
||
return Number.isFinite(n) && n >= 0 ? n : NaN;
|
||
}
|
||
|
||
function getRows() {
|
||
return Array.from(tbody.querySelectorAll('tr'));
|
||
}
|
||
|
||
function computeSum() {
|
||
const rows = getRows();
|
||
|
||
let hasNamed = false;
|
||
let sumAll = 0; // suma ze wszystkich wierszy z nazwą i poprawną ceną
|
||
let sumToBuy = 0; // suma tylko z wierszy NIE oznaczonych jako "Kupione"
|
||
|
||
for (const tr of rows) {
|
||
const nameInput = tr.querySelector('input[name="item_nazwa[]"]');
|
||
const priceInput = tr.querySelector('input[name="item_cena[]"]');
|
||
const kupioneSwitch = tr.querySelector('.kupione-switch');
|
||
|
||
const name = nameInput ? nameInput.value.trim() : '';
|
||
if (!name) continue; // ignoruj puste wiersze bez nazwy
|
||
|
||
hasNamed = true;
|
||
|
||
const priceVal = priceInput ? parsePrice(priceInput.value) : NaN;
|
||
if (Number.isNaN(priceVal)) continue;
|
||
|
||
// zawsze dolicz do sumy wszystkich
|
||
sumAll += priceVal;
|
||
|
||
// do sumy do-kupienia tylko jeśli nie jest oznaczone jako kupione
|
||
if (!(kupioneSwitch && kupioneSwitch.checked)) {
|
||
sumToBuy += priceVal;
|
||
}
|
||
}
|
||
|
||
return { hasNamed, sumAll, sumToBuy };
|
||
}
|
||
|
||
|
||
function readCel() {
|
||
const v = parsePrice(celInput.value);
|
||
return Number.isNaN(v) ? null : v;
|
||
}
|
||
|
||
function formatPln(n) {
|
||
// Nie narzucamy locale – prosto 2 miejsca
|
||
return n.toFixed(2);
|
||
}
|
||
|
||
function updateUI() {
|
||
const { hasNamed, sumAll, sumToBuy } = computeSum();
|
||
|
||
// Brak produktów (brak nazw) lub obie sumy = 0 → nic nie pokazuj
|
||
if (!hasNamed || (sumAll <= 0 && sumToBuy <= 0)) {
|
||
box.classList.add('d-none');
|
||
btn.classList.add('d-none');
|
||
box.classList.remove('alert-success', 'alert-info');
|
||
msg.textContent = '';
|
||
return;
|
||
}
|
||
|
||
const cel = readCel();
|
||
const target = sumToBuy; // porównujemy do kwoty POZOSTAŁE DO KUPIENIA
|
||
|
||
// Jeśli cel nie ustawiony lub NaN → zaproponuj ustawienie celu = sumToBuy
|
||
if (cel === null) {
|
||
box.classList.remove('d-none');
|
||
box.classList.remove('alert-success');
|
||
box.classList.add('alert-info');
|
||
|
||
// pokazujemy obie sumy w komunikacie
|
||
msg.innerHTML = `
|
||
<div>Wszystkie: <strong>${formatPln(sumAll)} PLN</strong> ·
|
||
Do kupienia: <strong>${formatPln(sumToBuy)} PLN</strong></div>
|
||
<div class="mt-1">Możesz ustawić <strong>cel</strong> na kwotę do kupienia.</div>
|
||
`;
|
||
btn.textContent = `Ustaw cel = ${formatPln(target)} PLN`;
|
||
btn.classList.remove('d-none');
|
||
return;
|
||
}
|
||
|
||
// Mamy cel — porównanie do sumy do-kupienia
|
||
if (Math.abs(cel - target) <= EPS) {
|
||
box.classList.remove('d-none');
|
||
box.classList.remove('alert-info');
|
||
box.classList.add('alert-success');
|
||
msg.innerHTML = `
|
||
Suma <em>do kupienia</em> (<strong>${formatPln(target)} PLN</strong>) jest równa celowi.
|
||
<div class="small text-muted mt-1">Wszystkie: ${formatPln(sumAll)} PLN · Do kupienia: ${formatPln(sumToBuy)} PLN</div>
|
||
`;
|
||
btn.classList.add('d-none');
|
||
} else {
|
||
box.classList.remove('d-none');
|
||
box.classList.remove('alert-success');
|
||
box.classList.add('alert-info');
|
||
msg.innerHTML = `
|
||
<div>Wszystkie: <strong>${formatPln(sumAll)} PLN</strong> ·
|
||
Do kupienia: <strong>${formatPln(sumToBuy)} PLN</strong></div>
|
||
<div class="mt-1">Cel: <strong>${formatPln(cel)} PLN</strong></div>
|
||
`;
|
||
btn.textContent = `Zaktualizuj cel do ${formatPln(target)} PLN`;
|
||
btn.classList.remove('d-none');
|
||
}
|
||
}
|
||
|
||
btn.addEventListener('click', (e) => {
|
||
e.preventDefault();
|
||
const { sumToBuy } = computeSum();
|
||
if (sumToBuy > 0) {
|
||
celInput.value = formatPln(sumToBuy);
|
||
celInput.dispatchEvent(new Event('input', { bubbles: true }));
|
||
celInput.dispatchEvent(new Event('change', { bubbles: true }));
|
||
updateUI();
|
||
}
|
||
});
|
||
|
||
// Reaguj na zmiany cen/nazw
|
||
tbody.addEventListener('input', (e) => {
|
||
const name = e.target.getAttribute('name');
|
||
if (name === 'item_nazwa[]' || name === 'item_cena[]') {
|
||
updateUI();
|
||
}
|
||
});
|
||
|
||
// Reaguj na zmiany celu
|
||
celInput.addEventListener('input', updateUI);
|
||
celInput.addEventListener('change', updateUI);
|
||
|
||
// Obserwuj dodawanie/usuwanie wierszy przez inne skrypty
|
||
const mo = new MutationObserver(() => updateUI());
|
||
mo.observe(tbody, { childList: true, subtree: true });
|
||
|
||
// Init po załadowaniu
|
||
document.addEventListener('DOMContentLoaded', updateUI);
|
||
// i jedno wywołanie na starcie (gdy DOMContentLoaded już był)
|
||
updateUI();
|
||
})();
|