/* Учёт заявок на пропуск — демо: хранение в localStorage.
Демо-набор отдельно (key "kt_pass_demo_seed") от добавленных пользователем записей
(key "kt_pass_requests") — показываем как есть, без смешивания и подмены. */
var STATUS = {
new: { label: "Новая", pill: "info" },
processing: { label: "В обработке", pill: "warn" },
approved: { label: "Одобрена", pill: "ok" },
rejected: { label: "Отклонена", pill: "risk" }
};
var STATUS_ORDER = ["new", "processing", "approved", "rejected"];
var DEMO = [
{ id: 1042, name: "Ахметов Ерлан Сергеевич", purpose: "Въезд на технологическую территорию ЦОД Алматы", date: "2026-09-18" },
{ id: 1041, name: "Бекеева Алия Нурлановна", purpose: "Обучение: работа с ОДЗ, учебный класс B", date: "2026-09-17" },
{ id: 1040, name: "Сериков Данияр Олегович", purpose: "Работа подрядчика, зона монтажа №3", date: "2026-09-16" },
{ id: 1039, name: "Махамбетова Гульнара", purpose: "Ревизия склада СИЗ", date: "2026-09-15" },
{ id: 1038, name: "Токтаров Нурлан", purpose: "Въезд на территорию офиса №2", date: "2026-09-15" },
{ id: 1037, name: "Абдрахманова Семина", purpose: "Курсы ИБ, 2 день", date: "2026-09-12" },
{ id: 1036, name: "Куанышбаев Асхат", purpose: "Сопровождение инспекции", date: "2026-09-12" },
{ id: 1035, name: "Омарова Жания", purpose: "Подача документов в отдел кадров", date: "2026-09-10" },
{ id: 1034, name: "Нурланов Серик", purpose: "Доставка оборудования, грузовой въезд", date: "2026-09-05" }
];
var DEMO_STATUS = { 1042: "new", 1041: "new", 1040: "processing", 1039: "processing", 1038: "approved", 1037: "approved", 1036: "rejected", 1035: "rejected", 1034: "approved" };
/** Демо-набор: статусы приложены и зафиксированы, перезаписывать нельзя. */
function demoItems() {
return DEMO.map(function (d) {
return { id: d.id, name: d.name, purpose: d.purpose, date: d.date, status: DEMO_STATUS[d.id], demo: true };
});
}
/** Записи, добавленные пользователем в этой сессии браузера. */
function loadUser() {
try {
var raw = localStorage.getItem("kt_pass_requests");
var arr = raw ? JSON.parse(raw) : [];
return Array.isArray(arr) ? arr.filter(function (r) { return isReq(r); }) : [];
} catch (e) {
return [];
}
}
function saveUser(arr) {
try {
localStorage.setItem("kt_pass_requests", JSON.stringify(arr));
} catch (e) {
/* localStorage недоступен — работаем только в памяти */
}
}
function isReq(r) {
return r && r.name && r.purpose && r.date && STATUS[r.status] != null && r.id > 0;
}
function nextId(user) {
var m = 0;
user.forEach(function (r) { if (r.id > m) m = r.id; });
return 10000 + user.length + 1 + (m >= 10000 ? m - 9999 : 0);
}
var state = { filter: "all", user: loadUser() };
var $form = document.getElementById("request-form");
var $kpiStrip = document.getElementById("kpi-strip");
var $tableWrap = document.getElementById("table-wrap");
var $tbody = document.getElementById("list-body");
var $empty = document.getElementById("list-empty");
var $emptyHint = document.getElementById("list-empty-hint");
var $total = document.getElementById("list-total");
var $toastStack = document.getElementById("toast-stack");
function esc(s) {
return String(s).replace(/[&<>"']/g, function (c) {
return { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c];
});
}
function pad(n) { return String(n).length < 2 ? "0" + n : String(n); }
function fmtDate(iso) {
if (!iso) return "—";
var parts = iso.split("-");
if (parts.length !== 3) return iso;
return parts[2] + "." + parts[1] + "." + parts[0];
}
function statusInfo(s) {
return STATUS[s] || STATUS.new;
}
function allItems() {
var merged = state.user.map(function (r) {
return { id: r.id, name: r.name, purpose: r.purpose, date: r.date, status: r.status, demo: false };
}).concat(demoItems());
merged.sort(function (a, b) { return b.id - a.id; });
return merged;
}
function visible() {
var all = allItems();
if (state.filter === "all") return all;
return all.filter(function (r) { return r.status === state.filter; });
}
function renderKPI() {
var all = allItems();
var counts = { all: all.length };
STATUS_ORDER.forEach(function (k) { counts[k] = 0; });
all.forEach(function (r) { counts[r.status] = (counts[r.status] || 0) + 1; });
function kpi(id, value, label) {
var active = state.filter === id ? "true" : "false";
return '
' +
'' + value + "" +
'' + label + "" +
"
";
}
var KPIS = [
["all", "Всего"],
["new", "Новые"],
["processing", "В обработке"],
["approved", "Одобрено"],
["rejected", "Отклонено"]
];
var parts = KPIS.map(function (k) { return kpi(k[0], counts[k[0]], k[1]); });
$kpiStrip.innerHTML = parts.join("");
}
function plural(n, one, few, many) {
var n10 = n % 10, n100 = n % 100;
if (n10 === 1 && n100 !== 11) return one;
if (n10 >= 2 && n10 <= 4 && (n100 < 12 || n100 > 14)) return few;
return many;
}
function renderList() {
var list = visible();
var total = allItems().length;
$total.textContent = total + " " + plural(total, "заявка", "заявки", "заявок");
if (list.length === 0) {
$tbody.innerHTML = "";
$tableWrap.hidden = true;
$empty.hidden = false;
$emptyHint.textContent = state.filter === "all"
? "Заявок пока нет — создайте первую в форме выше."
: "Под выбранный статус заявки не нашлись.";
return;
}
$tableWrap.hidden = false;
$empty.hidden = true;
var rows = list.map(function (r) {
var st = statusInfo(r.status);
var actions = "";
if (!r.demo) {
if (r.status === "new") {
actions += btnAction(r.id, "processing", "check", "В обработку");
} else if (r.status === "approved") {
actions += btnAction(r.id, "new", "refresh", "Сменить статус");
}
actions += btnAction(r.id, "delete", "trash", "Удалить", "ghost");
}
return "" +
'| ' + r.id + " | " +
"" + esc(r.name) + " | " +
'' + esc(r.purpose) + " | " +
'' + fmtDate(r.date) + " | " +
'' + st.label + " | " +
'' + (actions || "—") + " | " +
"
";
});
$tbody.innerHTML = rows.join("");
}
function btnAction(id, target, icon, label, variant) {
return '";
}
function render() {
renderKPI();
renderList();
}
function toast(text, tone) {
var el = document.createElement("div");
el.className = "kt-ai-toast";
if (tone) el.setAttribute("data-tone", tone);
el.textContent = text;
$toastStack.appendChild(el);
setTimeout(function () { el.remove(); }, 4000);
}
function setInvalid(input, bad) {
input.setAttribute("data-invalid", bad ? "true" : "false");
var field = input.closest(".kt-ai-field");
if (field) {
var err = field.querySelector(".error");
if (err) err.hidden = !bad;
field.setAttribute("data-invalid", bad ? "true" : "false");
}
}
function setFilter(s) {
state.filter = s;
document.querySelectorAll(".kt-ai-filter-chip[data-status]").forEach(function (c) {
c.setAttribute("data-active", c.getAttribute("data-status") === s ? "true" : "false");
});
renderKPI();
renderList();
}
document.addEventListener("click", function (e) {
var chip = e.target.closest(".kt-ai-filter-chip[data-status]");
if (chip) { setFilter(chip.getAttribute("data-status")); return; }
var kpi = e.target.closest(".kt-ai-kpi[data-status]");
if (kpi) { setFilter(kpi.getAttribute("data-status")); return; }
var act = e.target.closest(".kt-ai-btn[data-action]");
if (act) {
var id = Number(act.getAttribute("data-id"));
var target = act.getAttribute("data-action");
state.user = state.user.filter(function (r) {
if (r.id !== id) return true;
if (target === "delete") { toast("Заявка №" + id + " удалена"); return false; }
r.status = target;
toast(
target === "processing" ? "Заявка №" + id + " перенесена в обработку" :
target === "approved" ? "Заявка №" + id + " одобрена" :
"Статус заявки №" + id + ": " + statusInfo(target).label
);
return true;
});
saveUser(state.user);
render();
}
});
document.getElementById("btn-reset").addEventListener("click", function () { setFilter("all"); });
["f-name", "f-purpose", "f-date"].forEach(function (i) {
document.getElementById(i).addEventListener("input", function () { setInvalid(this, false); });
});
$form.addEventListener("submit", function (e) {
e.preventDefault();
var f = $form;
var name = f.elements["f-name"].value.trim();
var purpose = f.elements["f-purpose"].value.trim();
var date = f.elements["f-date"].value;
var ok = true;
if (!name) { setInvalid(f.elements["f-name"], true); ok = false; }
if (!purpose) { setInvalid(f.elements["f-purpose"], true); ok = false; }
if (!date) { setInvalid(f.elements["f-date"], true); ok = false; }
if (!ok) { toast("Проверьте поля формы", "warn"); return; }
var item = { id: nextId(state.user), name: name, purpose: purpose, date: date, status: "new" };
state.user.push(item);
saveUser(state.user);
f.reset();
render();
toast("Заявка №" + item.id + " создана, статус: Новая");
$form.scrollIntoView({ behavior: "smooth", block: "nearest" });
});
(function init() {
var today = new Date();
document.getElementById("f-date").valueAsDate = today;
render();
})();