cake-order-tracker/server/static/order.js
2026-06-15 20:15:12 +02:00

340 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

var subtotal = 0;
var editingSpecialId = null;
var activeCatalogueTags = [];
var activeCakeTags = [];
function openSpecialCakeOverlay() {
editingSpecialId = null;
document.getElementById('sc-overlay-title').textContent = 'Dodaj tort specjalny';
document.getElementById('sc-name').value = '';
document.getElementById('sc-price').value = '';
document.getElementById('sc-size').value = '';
document.getElementById('sc-shape').value = '';
document.getElementById('sc-flavour').value = '';
document.getElementById('sc-notes').value = '';
document.getElementById('sc-new-tag').value = '';
var cbs = document.querySelectorAll('.sc-tag-cb');
for (var i = 0; i < cbs.length; i++) cbs[i].checked = false;
document.getElementById('sc-overlay').classList.add('open');
document.getElementById('sc-name').focus();
}
function closeSpecialCakeOverlay() {
document.getElementById('sc-overlay').classList.remove('open');
editingSpecialId = null;
}
function getOverlayFormData() {
return {
name: document.getElementById('sc-name').value.trim(),
price: document.getElementById('sc-price').value,
size: document.getElementById('sc-size').value.trim(),
shape: document.getElementById('sc-shape').value,
flavour: document.getElementById('sc-flavour').value.trim(),
notes: document.getElementById('sc-notes').value.trim(),
tagIds: (function() {
var ids = [];
var cbs = document.querySelectorAll('.sc-tag-cb:checked');
for (var i = 0; i < cbs.length; i++) ids.push(cbs[i].value);
return ids;
})(),
tagNames: (function() {
var names = [];
var cbs = document.querySelectorAll('.sc-tag-cb:checked');
for (var i = 0; i < cbs.length; i++)
names.push(cbs[i].closest('.tag-chip').textContent.trim());
return names;
})(),
newTag: document.getElementById('sc-new-tag').value.trim()
};
}
function buildSpecialCakeHTML(d) {
var parts = [];
if (d.size) parts.push(d.size);
if (d.flavour) parts.push(d.flavour);
if (d.shape === 'round') parts.push('okragly');
else if (d.shape === 'square') parts.push('kwadrat');
if (d.notes) parts.push('notatka: ' + d.notes);
var detail = parts.length ? parts.join(', ') : '';
var tagHtml = d.tagNames.length > 0 || d.newTag ? '<div class="basket-item-tags">' : '';
for (var i = 0; i < d.tagNames.length; i++)
tagHtml += '<span class="tag-chip sm">' + d.tagNames[i] + '</span>';
if (d.newTag)
tagHtml += '<span class="tag-chip sm">' + d.newTag + '</span>';
if (d.tagNames.length > 0 || d.newTag) tagHtml += '</div>';
var priceVal = Number(d.price).toFixed(2);
var tagIdsStr = d.tagIds.join(',');
var html =
'<div class="basket-item-body">' +
'<div class="name">' + d.name + '</div>' +
'<div class="detail">' + detail + '</div>' +
tagHtml +
'</div>' +
'<div class="price">' + priceVal + ' PLN</div>' +
'<div class="basket-item-actions">' +
'<button type="button" class="btn-icon" onclick="editSpecialCake(this)" title="Edytuj">' +
'<span class="material-symbols-outlined">edit</span></button>' +
'<button type="button" class="remove" onclick="removeSpecialCake(this)" title="Usuń">' +
'<span class="material-symbols-outlined">close</span></button>' +
'</div>' +
'<input type="hidden" name="special_name[]" value="' + d.name + '">' +
'<input type="hidden" name="special_price[]" value="' + d.price + '">' +
'<input type="hidden" name="special_size[]" value="' + d.size + '">' +
'<input type="hidden" name="special_shape[]" value="' + d.shape + '">' +
'<input type="hidden" name="special_flavour[]" value="' + d.flavour + '">' +
'<input type="hidden" name="special_notes[]" value="' + d.notes + '">' +
'<input type="hidden" name="special_tags[]" value="' + tagIdsStr + '">';
if (d.newTag)
html += '<input type="hidden" name="special_new_tag[]" value="' + d.newTag + '">';
return html;
}
function saveSpecialCake() {
var d = getOverlayFormData();
if (!d.name) return;
if (editingSpecialId) {
var item = document.querySelector('#basket-items li[data-special-id="' + editingSpecialId + '"]');
if (item) {
item.innerHTML = buildSpecialCakeHTML(d);
}
} else {
d.id = Date.now();
var item = document.createElement('li');
item.setAttribute('data-special-id', d.id);
item.innerHTML = buildSpecialCakeHTML(d);
document.getElementById('basket-items').appendChild(item);
}
closeSpecialCakeOverlay();
updateTotals();
}
function editSpecialCake(btn) {
var item = btn.closest('li');
var id = item.getAttribute('data-special-id');
editingSpecialId = id;
document.getElementById('sc-overlay-title').textContent = 'Edytuj tort specjalny';
var hidden = item.querySelectorAll('input[type="hidden"]');
var vals = {};
for (var i = 0; i < hidden.length; i++) {
var name = hidden[i].getAttribute('name');
vals[name] = hidden[i].value;
}
document.getElementById('sc-name').value = vals['special_name[]'] || '';
document.getElementById('sc-price').value = vals['special_price[]'] || '';
document.getElementById('sc-size').value = vals['special_size[]'] || '';
document.getElementById('sc-shape').value = vals['special_shape[]'] || '';
document.getElementById('sc-flavour').value = vals['special_flavour[]'] || '';
document.getElementById('sc-notes').value = vals['special_notes[]'] || '';
var currentTagIds = (vals['special_tags[]'] || '').split(',').filter(function(x) { return x; });
document.getElementById('sc-new-tag').value = '';
var cbs = document.querySelectorAll('.sc-tag-cb');
for (var i = 0; i < cbs.length; i++) {
cbs[i].checked = currentTagIds.indexOf(cbs[i].value) >= 0;
}
document.getElementById('sc-overlay').classList.add('open');
document.getElementById('sc-name').focus();
}
function removeSpecialCake(btn) {
btn.closest('li').remove();
updateTotals();
}
function changeCake(id, name, price, delta) {
var input = document.querySelector('[name="cake[' + id + ']"]');
if (input != null) {
var qty = Number(input.value) + delta;
if (qty <= 0) {
input.closest('li').remove();
updateTotals();
updateCatalogueQty(id, 0);
return;
}
input.value = qty;
var item = input.closest('li');
item.querySelector('.qty').innerText = qty;
item.querySelector('.price').innerText = price * qty + ' PLN';
updateTotals();
updateCatalogueQty(id, qty);
return;
}
if (delta <= 0) return;
var item = document.createElement('li');
item.setAttribute('data-cake-id', id);
item.innerHTML =
'<div class="basket-item-body">' +
'<div class="name">' + name + '</div>' +
'<div class="detail">' + price + ' PLN × <span class="qty">1</span></div>' +
'</div>' +
'<div class="price">' + price + ' PLN</div>' +
'<button type="button" class="remove" onclick="removeCake(this)">' +
'<span class="material-symbols-outlined">close</span>' +
'</button>' +
'<input type="hidden" name="cake[' + id + ']" value="1">';
document.getElementById('basket-items').appendChild(item);
updateTotals();
updateCatalogueQty(id, 1);
}
function removeCake(btn) {
var item = btn.closest('li');
var id = item.getAttribute('data-cake-id');
item.remove();
updateTotals();
updateCatalogueQty(id, 0);
}
function updatePrepaid() {
var paid = Number(document.querySelector('[name="paid"]')?.value || 0);
document.getElementById('paid-amount').innerText = paid.toFixed(2) + ' PLN';
document.getElementById('total-price').innerText = (subtotal - paid).toFixed(2) + ' PLN';
}
function updateTotals() {
subtotal = 0;
var items = document.querySelectorAll('#basket-items li');
items.forEach(function (item) {
var priceText = item.querySelector('.price').innerText;
var price = Number(priceText.split(' ')[0]);
if (item.hasAttribute('data-special-id')) {
subtotal += price;
} else {
var qty = Number(item.querySelector('.qty').innerText);
subtotal += price * qty;
}
});
document.getElementById('subtotal-price').innerText = subtotal.toFixed(2) + ' PLN';
updatePrepaid();
}
function updateCatalogueQty(id, qty) {
var el = document.getElementById('qty-' + id);
if (el) el.innerText = qty;
}
function toggleCatalogueTagFilter(btn) {
var tag = btn.getAttribute('data-tag');
var idx = activeCatalogueTags.indexOf(tag);
if (idx >= 0) {
activeCatalogueTags.splice(idx, 1);
btn.classList.remove('active');
} else {
activeCatalogueTags.push(tag);
btn.classList.add('active');
}
applyCatalogueFilters();
}
function getCatalogueTextQuery() {
var input = document.querySelector('#catalogue-grid').closest('.card').querySelector('input[type="text"]');
return input ? input.value.toLowerCase() : '';
}
function applyCatalogueFilters() {
var query = getCatalogueTextQuery();
var items = document.querySelectorAll('#catalogue-grid > li');
items.forEach(function (item) {
var name = item.getAttribute('data-name').toLowerCase();
var matchesText = name.includes(query);
var matchesTags = true;
if (activeCatalogueTags.length > 0) {
var itemTags = (item.getAttribute('data-tags') || '').split(',');
for (var i = 0; i < activeCatalogueTags.length; i++) {
if (itemTags.indexOf(activeCatalogueTags[i]) < 0) {
matchesTags = false;
break;
}
}
}
item.classList.toggle('hide', !(matchesText && matchesTags));
});
}
function filterCatalogue(input) {
applyCatalogueFilters();
}
function toggleCakeTagFilter(btn) {
var tag = btn.getAttribute('data-tag');
var idx = activeCakeTags.indexOf(tag);
if (idx >= 0) {
activeCakeTags.splice(idx, 1);
btn.classList.remove('active');
} else {
activeCakeTags.push(tag);
btn.classList.add('active');
}
var rows = document.querySelectorAll('#cakes-card tbody tr');
for (var i = 0; i < rows.length; i++) {
if (activeCakeTags.length === 0) { rows[i].classList.remove('hide'); continue; }
var rowTags = (rows[i].getAttribute('data-tags') || '').split(',');
var match = false;
for (var j = 0; j < activeCakeTags.length; j++) {
if (rowTags.indexOf(activeCakeTags[j]) >= 0) { match = true; break; }
}
rows[i].classList.toggle('hide', !match);
}
}
function filterOrders(input) {
var q = input.value.toLowerCase();
var table = input.closest('.card').querySelector('.data-table');
if (!table) return;
var rows = table.querySelectorAll('tbody tr');
for (var i = 0; i < rows.length; i++) {
var id = rows[i].children[0].textContent.toLowerCase();
var customer = rows[i].children[1].textContent.toLowerCase();
rows[i].classList.toggle('hide', !(id.includes(q) || customer.includes(q)));
}
}
function setLocation(btn, value) {
var group = btn.closest('.toggle-group');
group.querySelectorAll('.toggle-btn').forEach(function(b) { b.classList.remove('active'); });
btn.classList.add('active');
group.querySelector('input[type="hidden"]').value = value;
}
function confirmBlockedDate(form) {
var date = form.querySelector('[name="date"]').value;
var blocked = JSON.parse(form.getAttribute('data-blocked-dates') || '[]');
var hasSpecial = form.querySelector('[name="special_name[]"]');
if (hasSpecial && blocked.indexOf(date) >= 0) {
return confirm('Data ' + date + ' jest zablokowana dla zamówień z tortami specjalnymi. Czy na pewno chcesz kontynuować?');
}
return true;
}
function initOrderPage() {
var form = document.querySelector('.order-form');
if (!form) return;
var state = form.getAttribute('data-state');
if (state) {
try {
var data = JSON.parse(state);
for (var id in data) {
updateCatalogueQty(Number(id), data[id]);
}
} catch(e) {}
}
updateTotals();
}
function setActiveLink() {
var path = window.location.pathname;
var links = document.querySelectorAll('nav > a');
for (var i = 0; i < links.length; i++) {
links[i].classList.toggle('active', links[i].getAttribute('href') === path);
}
}
document.addEventListener('DOMContentLoaded', function() {
setActiveLink();
initOrderPage();
});
document.addEventListener('htmx:afterSettle', function() {
setActiveLink();
initOrderPage();
});