var items = []; var filterText = ""; async function load() { items = await fetch("/api/items").then(function(r) { return r.json(); }); render(); } function isComplete(r) { return r.city && r.summa && r.date && r.fileSection && r.fio && r.docSection && r.payment && r.fileAttachment && r.docAttachment; } function paymentBadge(val) { if (val === "оплачено") return '💰 ' + val + ''; if (val === "в ожидании") return '⏳ ' + val + ''; return '❌ ' + (val || "") + ''; } function render() { var q = filterText.toLowerCase(); var filtered = items.filter(function(i) { return !q || (i.city || "").toLowerCase().indexOf(q) !== -1 || (i.fio || "").toLowerCase().indexOf(q) !== -1 || (i.fileSection || "").toLowerCase().indexOf(q) !== -1 || (i.docSection || "").toLowerCase().indexOf(q) !== -1 || (i.payment || "").toLowerCase().indexOf(q) !== -1; }); var tbody = document.getElementById("tbody"); var empty = document.getElementById("empty"); if (filtered.length === 0) { tbody.innerHTML = ""; empty.style.display = "block"; } else { empty.style.display = "none"; tbody.innerHTML = filtered.map(function(r) { var fileLink = r.fileAttachment ? '📎 ' + esc(r.fileAttachment.name) + '' : ''; var docLink = r.docAttachment ? '📎 ' + esc(r.docAttachment.name) + '' : ''; var payLink = r.paymentAttachment ? '
📎 ' + esc(r.paymentAttachment.name) + '' : ''; var rowClass = isComplete(r) ? ' class="row-complete"' : ''; return "" + "" + esc(r.city) + "" + "" + (r.summa ? Number(r.summa).toLocaleString("ru-RU") : "") + " ₸" + "" + esc(r.date) + "" + "
" + esc(r.fileSection) + "
" + fileLink + "" + "" + esc(r.fio) + "" + "
" + esc(r.docSection) + "
" + docLink + "" + "" + paymentBadge(r.payment) + payLink + "" + '' + '' + '' + "" + ""; }).join(""); } updateStats(filtered); } function updateStats(filtered) { var total = items.length; var shown = filtered.length; var sum = filtered.reduce(function(s, r) { return s + (parseFloat(r.summa) || 0); }, 0); document.getElementById("stats").innerHTML = 'Всего: ' + total + '' + 'Показано: ' + shown + '' + 'Сумма: ' + sum.toLocaleString("ru-RU") + ' ₸'; } function esc(s) { return (s || "").replace(/&/g,"&").replace(//g,">"); } function openForm() { document.getElementById("modal").style.display = "flex"; document.getElementById("formTitle").textContent = "Новая запись"; document.getElementById("form").reset(); document.getElementById("editId").value = ""; document.getElementById("previewFile").innerHTML = ""; document.getElementById("previewDoc").innerHTML = ""; document.getElementById("previewPayment").innerHTML = ""; } function closeForm() { document.getElementById("modal").style.display = "none"; } async function uploadFile(inputName) { var input = document.querySelector("[name='" + inputName + "']"); if (!input || !input.files || !input.files[0]) return null; var formData = new FormData(); formData.append("file", input.files[0]); var resp = await fetch("/api/upload", { method: "POST", body: formData }); var result = await resp.json(); if (result.ok && result.files && result.files[0]) return result.files[0]; return null; } async function saveItem(e) { e.preventDefault(); var form = e.target; var fileData = await uploadFile("fileAttachment"); var docData = await uploadFile("docAttachment"); var payData = await uploadFile("paymentAttachment"); var data = { city: form.city.value, summa: form.summa.value, date: form.date.value, fileSection: form.fileSection.value, fio: form.fio.value, docSection: form.docSection.value, payment: form.payment.value }; var editId = document.getElementById("editId").value; if (editId) { var existing = items.find(function(i) { return i.id === parseInt(editId); }); data.fileAttachment = fileData || (existing ? existing.fileAttachment : null); data.docAttachment = docData || (existing ? existing.docAttachment : null); data.paymentAttachment = payData || (existing ? existing.paymentAttachment : null); await fetch("/api/items/" + editId, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }); } else { data.fileAttachment = fileData; data.docAttachment = docData; data.paymentAttachment = payData; await fetch("/api/items", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }); } closeForm(); load(); } async function editItem(id) { var item = items.find(function(i) { return i.id === id; }); if (!item) return; document.getElementById("modal").style.display = "flex"; document.getElementById("formTitle").textContent = "Изменить запись"; document.getElementById("editId").value = id; document.querySelector("[name=city]").value = item.city || ""; document.querySelector("[name=summa]").value = item.summa || ""; document.querySelector("[name=date]").value = item.date || ""; document.querySelector("[name=fileSection]").value = item.fileSection || ""; document.querySelector("[name=fio]").value = item.fio || ""; document.querySelector("[name=docSection]").value = item.docSection || ""; document.querySelector("[name=payment]").value = item.payment || ""; document.getElementById("previewFile").innerHTML = item.fileAttachment ? '📎 ' + esc(item.fileAttachment.name) + '' : ''; document.getElementById("previewDoc").innerHTML = item.docAttachment ? '📎 ' + esc(item.docAttachment.name) + '' : ''; document.getElementById("previewPayment").innerHTML = item.paymentAttachment ? '📎 ' + esc(item.paymentAttachment.name) + '' : ''; } async function deleteItem(id) { if (!confirm("Удалить запись?")) return; await fetch("/api/items/" + id, { method: "DELETE" }); load(); } document.getElementById("search").addEventListener("input", function(e) { filterText = e.target.value; render(); }); function exportCsv() { if (items.length === 0) { alert("Нет данных для выгрузки"); return; } var head = ["Город","Сумма","Дата","Раздел для файла","Файл","ФИО","Раздел для документов","Документ","Платёж","Файл оплаты"]; var body = items.map(function(r) { return [r.city, r.summa, r.date, r.fileSection, r.fileAttachment ? r.fileAttachment.name : "", r.fio, r.docSection, r.docAttachment ? r.docAttachment.name : "", r.payment, r.paymentAttachment ? r.paymentAttachment.name : ""] .map(function(v) { return '"' + String(v || "").replace(/"/g, '""') + '"'; }) .join(";"); }); var csv = "\uFEFF" + [head.join(";"), ...body].join("\n"); var a = document.createElement("a"); a.href = URL.createObjectURL(new Blob([csv], { type: "text/csv" })); a.download = "otchet.csv"; a.click(); } load();