/* Журнал заявок на ремонт оборудования. Данные в localStorage. */
(function () {
"use strict";
var STORAGE_KEY = "remont-zayavki-v1";
var ICON_BASE = "design-system/icons/kt-ai-lucide-sprite.svg";
var STATUSES = [
{ id: "new", label: "Новая", tone: "info" },
{ id: "work", label: "В работе", tone: "warn" },
{ id: "wait", label: "Ожидает запчасть", tone: "risk" },
{ id: "planned", label: "Запланирована", tone: "info" },
{ id: "done", label: "Исправлена", tone: "ok" }
];
/* ---------- даты ---------- */
function pad(n) { return (n < 10 ? "0" : "") + n; }
function dstr(offset) {
var d = new Date();
d.setDate(d.getDate() + (offset || 0));
return d.getFullYear() + "-" + pad(d.getMonth() + 1) + "-" + pad(d.getDate());
}
function fmtDate(iso) {
if (!iso) return "—";
var p = iso.split("-");
return p.length === 3 ? p[2] + "." + p[1] + "." + p[0] : iso;
}
function fmtWhen(iso) {
var d = new Date(iso);
if (isNaN(d.getTime())) return String(iso);
return pad(d.getDate()) + "." + pad(d.getMonth() + 1) + "." + d.getFullYear() +
" " + pad(d.getHours()) + ":" + pad(d.getMinutes());
}
function daysDiff(iso) {
var a = new Date(dstr(0) + "T00:00:00").getTime();
var b = new Date(iso.replace("T", " ") + ":00").getTime();
return Math.round((b - a) / 86400000);
}
function deadlineLabel(r) {
if (r.status === "done") return fmtDate(r.deadline) + " · закрыта";
var df = daysDiff(r.deadline);
if (df < 0) return fmtDate(r.deadline) + " · просрочено";
if (df === 0) return fmtDate(r.deadline) + " · сегодня";
if (df === 1) return fmtDate(r.deadline) + " · завтра";
return fmtDate(r.deadline) + " · через " + df + " дн.";
}
/* ---------- примерные данные ---------- */
var SEED_ITEMS = [
{ id: 1, person: "Айдар Сериков", what: "Принтер в переговорной «Сары-Арка» — замятие бумаги", deadline: -3, status: "work", submitted: -8, note: "Требуется замена картриджа. Обслуживание по средам." },
{ id: 2, person: "Нурсултан Ахметов", what: "Телевизор в актовом зале без изображения", deadline: 0, status: "wait", submitted: -5, note: "Ожидается поставка блока питания." },
{ id: 3, person: "Дарья Ким", what: "Кондиционер в кабинете 4-12 не холодит", deadline: 2, status: "work", submitted: -2, note: "Требуется дозаправка фреоном." },
{ id: 4, person: "Ержан Нурланов", what: "Кресло руководителя — сломан подлокотник", deadline: 3, status: "planned", submitted: -4, note: "Назначено на пятницу 10:00." },
{ id: 5, person: "Айгерим Тлеубердиева", what: "Компьютер (рабочее место 2-07) не включается", deadline: -1, status: "work", submitted: -3, note: "Диагностика блока питания." },
{ id: 6, person: "Мадина Исмагулова", what: "Сканер в отделе кадров рвёт листы", deadline: 6, status: "new", submitted: 0, note: "" },
{ id: 7, person: "Тимур Рахимов", what: "Монитор в переговорной №3 — вертикальные полосы", deadline: -2, status: "done", submitted: -12, note: "Заменён шлейф матрицы." },
{ id: 8, person: "Айбек Тастанбеков", what: "Система видеонаблюдения — камера у входа не пишет", deadline: 1, status: "work", submitted: -1, note: "Требуется замена HDD регистратора." },
{ id: 9, person: "Гузель Омарова", what: "Кофемашина в комнате отдыха течёт из-под чашки", deadline: -3, status: "done", submitted: -9, note: "Заменён уплотнитель, резервуар промыт." },
{ id: 10, person: "Олеся Бекенова", what: "Свет в коридоре 3-го этажа — мигает группа ламп", deadline: 14, status: "new", submitted: 0, note: "" }
];
var SEED_LOG = [
{ offset: -12, time: "13:10", user: "Тимур Рахимов", what: "Заявка №7 подана" },
{ offset: -9, time: "10:25", user: "Гузель Омарова", what: "Заявка №9 подана" },
{ offset: -8, time: "09:12", user: "Айдар Сериков", what: "Заявка №1 подана" },
{ offset: -8, time: "11:00", user: "Служба", what: "Заявка №7 — статус «В работе»" },
{ offset: -6, time: "14:30", user: "Служба", what: "Заявка №1 — статус «В работе»" },
{ offset: -5, time: "08:30", user: "Служба", what: "Заявка №9 — статус «В работе»" },
{ offset: -5, time: "11:05", user: "Нурсултан Ахметов", what: "Заявка №2 подана" },
{ offset: -4, time: "08:45", user: "Ержан Нурланов", what: "Заявка №4 подана" },
{ offset: -3, time: "10:30", user: "Айгерим Тлеубердиева", what: "Заявка №5 подана" },
{ offset: -3, time: "12:10", user: "Служба", what: "Заявка №9 — статус «Исправлена»" },
{ offset: -2, time: "16:20", user: "Дарья Ким", what: "Заявка №3 подана" },
{ offset: -1, time: "09:00", user: "Служба", what: "Заявка №5 — статус «В работе»" },
{ offset: -1, time: "11:30", user: "Нурсултан Ахметов", what: "Заявка №2 — статус «Ожидает запчасть»" },
{ offset: -1, time: "12:00", user: "Служба", what: "Заявка №4 — статус «Запланирована»" },
{ offset: -1, time: "17:05", user: "Айбек Тастанбеков", what: "Заявка №8 подана" },
{ offset: 0, time: "08:15", user: "Мадина Исмагулова", what: "Заявка №6 подана" },
{ offset: 0, time: "09:40", user: "Служба", what: "Заявка №8 — статус «В работе»" },
{ offset: 0, time: "10:05", user: "Служба", what: "Заявка №3 — статус «В работе»" },
{ offset: 0, time: "11:40", user: "Олеся Бекенова", what: "Заявка №10 подана" }
];
function applySeedDates() {
for (var i = 0; i < SEED_ITEMS.length; i++) {
var s = SEED_ITEMS[i];
s.submitted = dstr(s.submitted);
s.deadline = dstr(s.deadline);
delete s.submittedOffset;
delete s.deadlineOffset;
}
return SEED_ITEMS;
}
function buildSeed() {
var items = [];
applySeedDates();
for (var i = 0; i < SEED_ITEMS.length; i++) {
var s = SEED_ITEMS[i];
items.push({
id: s.id, person: s.person, what: s.what,
submitted: s.submitted, deadline: s.deadline,
status: s.status, note: s.note, events: seedEvents(s)
});
}
var log = [];
for (var j = 0; j < SEED_LOG.length; j++) {
var e = SEED_LOG[j];
log.push({ when: dstr(e.offset) + "T" + e.time + ":00", user: e.user, what: e.what });
}
log.sort(function (a, b) { return a.when < b.when ? 1 : -1; });
return { items: items, log: log };
}
function seedEvents(s) {
var ev = [{ when: s.submitted + "T09:15:00", user: s.person, what: "заявка подана" }];
var workDay = shiftDay(s.submitted, 1);
var nextDay = shiftDay(workDay, 1);
if (s.status === "done") ev.push({ when: s.deadline + "T15:00:00", user: "Служба", what: "статус: Исправлена" });
else if (s.status === "work") ev.push({ when: workDay + "T10:00:00", user: "Служба", what: "статус: В работе" });
else if (s.status === "wait") {
ev.push({ when: workDay + "T10:00:00", user: "Служба", what: "статус: В работе" });
ev.push({ when: nextDay + "T10:00:00", user: "Служба", what: "статус: Ожидает запчасть" });
} else if (s.status === "planned") ev.push({ when: workDay + "T10:00:00", user: "Служба", what: "статус: Запланирована" });
return ev;
}
function shiftDay(base, plus) {
var d = new Date(base + "T00:00:00");
d.setDate(d.getDate() + plus);
return d.getFullYear() + "-" + pad(d.getMonth() + 1) + "-" + pad(d.getDate());
}
function load() {
try {
var raw = localStorage.getItem(STORAGE_KEY);
if (raw) {
var d = JSON.parse(raw);
if (d && d.items) return d;
}
} catch (err) {}
var fresh = buildSeed();
try { localStorage.setItem(STORAGE_KEY, JSON.stringify(fresh)); } catch (err2) {}
return fresh;
}
function persist() {
try { localStorage.setItem(STORAGE_KEY, JSON.stringify(S)); } catch (err) {
toast("Не удалось сохранить данные", "risk");
}
}
function resetData() {
S = buildSeed();
try { localStorage.setItem(STORAGE_KEY, JSON.stringify(S)); } catch (err) {}
state.status = "all";
state.q = "";
var si = $("searchInput");
if (si) si.value = "";
renderAll();
toast("Данные возвращены к исходным", "ok");
}
var S = load();
var state = { status: "all", q: "", currentId: null, mode: null };
/* ---------- утилиты ---------- */
function $(id) { return document.getElementById(id); }
var ESC_MAP = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" };
function esc(s) {
return String(s == null ? "" : s).replace(/[&<>"']/g, function (c) {
return ESC_MAP[c];
});
}
function byId(id) {
for (var i = 0; i < S.items.length; i++) if (S.items[i].id === id) return S.items[i];
return null;
}
function nextId() {
var m = 1;
for (var i = 0; i < S.items.length; i++) if (S.items[i].id >= m) m = S.items[i].id + 1;
return m;
}
function statusOf(id) {
for (var i = 0; i < STATUSES.length; i++) if (STATUSES[i].id === id) return STATUSES[i];
return null;
}
function addLog(user, what) {
S.log.unshift({ when: new Date().toISOString(), user: user, what: what });
if (S.log.length > 100) S.log.length = 100;
persist();
}
function icon(name) {
return '';
}
function toast(msg, tone) {
var stack = $("toasts");
if (!stack) return;
var d = document.createElement("div");
d.className = "kt-ai-toast";
d.setAttribute("data-tone", tone || "ok");
d.textContent = msg;
stack.appendChild(d);
setTimeout(function () {
if (d.parentNode) d.parentNode.removeChild(d);
}, 3200);
}
/* ---------- форма ---------- */
var FIELD_TITLES = {
person: "Кто подал",
what: "Что сломалось",
deadline: "Срок ремонта",
status: "Статус",
note: "Комментарий"
};
function formHtml(mode) {
var r = state.currentId ? byId(state.currentId) : null;
var isNew = !r;
var p = r ? r.person : "";
var w = r ? r.what : "";
var today = dstr(0);
var dISO = r ? r.deadline : dstr(7);
var st = r ? r.status : "new";
var note = r ? r.note : "";
var h = '
' +
'
";
return h;
}
function statusOptions(sel) {
var h = "";
for (var i = 0; i < STATUSES.length; i++) {
var s = STATUSES[i];
h += '";
}
return h;
}
/* ---------- ящик ---------- */
function openDrawer() {
$("drawer").hidden = false;
$("drawerOverlay").hidden = false;
document.body.style.overflow = "hidden";
var closeBtn = $("drawerClose");
if (closeBtn) closeBtn.focus();
}
function closeDrawer() {
$("drawer").hidden = true;
$("drawerOverlay").hidden = true;
document.body.style.overflow = "";
state.mode = null;
state.currentId = null;
}
function openDetail(id) {
var r = byId(id);
if (!r) return;
state.currentId = id;
state.mode = "view";
openDrawer();
renderDetail(r);
}
function propLine(k, v) { return '
' + k + "" + v + "
"; }
function renderDetail(r) {
var st = statusOf(r.status);
var actions = "";
$("drawerTitle").textContent = "Заявка №" + r.id;
$("drawerMeta").textContent = "подана " + fmtDate(r.submitted);
var events = (r.events || []).slice().reverse();
var evHtml = "";
for (var i = 0; i < events.length && i < 8; i++) {
var e = events[i];
evHtml += '