448 lines
14 KiB
JavaScript
448 lines
14 KiB
JavaScript
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;
|
||
if (path === "/cake") {
|
||
path = "/cakes";
|
||
}
|
||
console.log(path);
|
||
var links = document.querySelectorAll("nav > a");
|
||
for (var i = 0; i < links.length; i++) {
|
||
links[i].classList.toggle("active", links[i].getAttribute("href") === path);
|
||
}
|
||
}
|
||
|
||
function viewSpecialCake(btn) {
|
||
var tr = btn.closest("tr");
|
||
document.getElementById("sc-view-title").textContent =
|
||
tr.getAttribute("data-sc-name");
|
||
document.getElementById("sc-view-name").textContent =
|
||
tr.getAttribute("data-sc-name");
|
||
document.getElementById("sc-view-price").textContent =
|
||
tr.getAttribute("data-sc-price") + " PLN";
|
||
document.getElementById("sc-view-size").textContent =
|
||
tr.getAttribute("data-sc-size") || "—";
|
||
var shapeVal = tr.getAttribute("data-sc-shape");
|
||
var shapeText = "";
|
||
if (shapeVal === "round") shapeText = "Okrągły";
|
||
else if (shapeVal === "square") shapeText = "Kwadrat";
|
||
else shapeText = shapeVal || "—";
|
||
document.getElementById("sc-view-shape").textContent = shapeText;
|
||
document.getElementById("sc-view-flavour").textContent =
|
||
tr.getAttribute("data-sc-flavour") || "—";
|
||
document.getElementById("sc-view-notes").textContent =
|
||
tr.getAttribute("data-sc-notes") || "—";
|
||
document.getElementById("sc-view-client").textContent =
|
||
tr.getAttribute("data-sc-client");
|
||
document.getElementById("sc-view-date").textContent =
|
||
tr.getAttribute("data-sc-date");
|
||
var tagsStr = tr.getAttribute("data-sc-tags");
|
||
var tagsContainer = document.getElementById("sc-view-tags");
|
||
tagsContainer.innerHTML = "";
|
||
if (tagsStr) {
|
||
var tagNames = tagsStr.split(",");
|
||
for (var i = 0; i < tagNames.length; i++) {
|
||
if (tagNames[i].trim()) {
|
||
var tag = document.createElement("span");
|
||
tag.className = "tag-chip sm";
|
||
tag.textContent = tagNames[i].trim();
|
||
tagsContainer.appendChild(tag);
|
||
}
|
||
}
|
||
document.getElementById("sc-view-tags-field").classList.remove("hide");
|
||
} else {
|
||
document.getElementById("sc-view-tags-field").classList.add("hide");
|
||
}
|
||
document.getElementById("sc-view-order-link").href =
|
||
"/order/" + tr.getAttribute("data-sc-order-id");
|
||
document.getElementById("sc-view-overlay").classList.add("open");
|
||
}
|
||
|
||
function closeViewSpecialCake() {
|
||
document.getElementById("sc-view-overlay").classList.remove("open");
|
||
}
|
||
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
setActiveLink();
|
||
initOrderPage();
|
||
});
|
||
|
||
document.addEventListener("htmx:afterSettle", function () {
|
||
setActiveLink();
|
||
initOrderPage();
|
||
});
|