// Демо-данные: 10 записей с реалистичными именами и датами const DEMO_DATA = [ { id: 1, fio: "Алиев А.С.", item: "Каска защитная", issueDate: "2025-01-15", returnDate: "2025-07-15", status: "В носке" }, { id: 2, fio: "Смирнова Е.В.", item: "Ботинки кожаные", issueDate: "2025-02-01", returnDate: "2025-06-01", status: "Просрочено" }, { id: 3, fio: "Ибрагимов Б.К.", item: "Костюм х/б", issueDate: "2025-03-10", returnDate: "2025-09-10", status: "В носке" }, { id: 4, fio: "Петров И.Д.", item: "Перчатки рабочие", issueDate: "2025-01-20", returnDate: "2025-04-20", status: "Просрочено" }, { id: 5, fio: "Ахметова Г.Т.", item: "Очки защитные", issueDate: "2025-04-05", returnDate: "2025-10-05", status: "В носке" }, { id: 6, fio: "Козлов М.А.", item: "Респиратор", issueDate: "2025-02-15", returnDate: "2025-05-15", status: "Сдано" }, { id: 7, fio: "Нурланова А.Е.", item: "Каска защитная", issueDate: "2025-05-01", returnDate: "2025-11-01", status: "В носке" }, { id: 8, fio: "Васильченко П.П.", item: "Наушники противошумные", issueDate: "2025-03-20", returnDate: "2025-08-20", status: "Просрочено" }, { id: 9, fio: "Омаров Д.Ж.", item: "Жилет сигнальный", issueDate: "2025-06-01", returnDate: "2025-12-01", status: "В носке" }, { id: 10, fio: "Тимофеева О.Л.", item: "Сапоги резиновые", issueDate: "2025-01-10", returnDate: "2025-03-10", status: "Сдано" } ]; // Ключи для localStorage const STORAGE_KEY = "specod_storage_v1"; const LOG_KEY = "specod_log_v1"; // Текущие данные let items = []; let logs = []; let currentFilter = "Все"; // Инициализация при загрузке document.addEventListener("DOMContentLoaded", () => { loadData(); renderFilters(); renderTable(); renderLog(); updateCounts(); }); // Загрузка данных из localStorage или демо function loadData() { const stored = localStorage.getItem(STORAGE_KEY); if (stored) { items = JSON.parse(stored); } else { items = [...DEMO_DATA]; saveToStorage(); } const storedLog = localStorage.getItem(LOG_KEY); if (storedLog) { logs = JSON.parse(storedLog); } else { logs = [{ type: "add", message: "Система инициализирована с демо-данными", timestamp: new Date().toISOString() }]; saveLogToStorage(); } } function saveToStorage() { localStorage.setItem(STORAGE_KEY, JSON.stringify(items)); } function saveLogToStorage() { localStorage.setItem(LOG_KEY, JSON.stringify(logs)); } // Фильтры function renderFilters() { const filters = ["Все", "В носке", "Сдано", "Просрочено"]; const container = document.getElementById("filters"); container.innerHTML = filters.map(f => `` ).join(""); } function setFilter(filter) { currentFilter = filter; renderFilters(); renderTable(); } // Таблица function renderTable() { const tbody = document.getElementById("table-body"); const search = document.getElementById("search").value.toLowerCase(); let filtered = items.filter(item => { // Обновляем статус просрочки item = updateItemStatus(item); // Фильтр по статусу if (currentFilter !== "Все" && item.status !== currentFilter) return false; // Поиск if (search) { return item.fio.toLowerCase().includes(search) || item.item.toLowerCase().includes(search); } return true; }); if (filtered.length === 0) { tbody.innerHTML = `
📋

Нет записей для отображения

`; updateCounts(); return; } tbody.innerHTML = filtered.map((item, idx) => { const isOverdue = item.status === "Просрочено"; return ` ${idx + 1} ${escapeHtml(item.fio)} ${escapeHtml(item.item)} ${formatDate(item.issueDate)} ${formatDate(item.returnDate)} ${item.status} `; }).join(""); updateCounts(); } // Обновление статуса на основе даты function updateItemStatus(item) { const today = new Date(); today.setHours(0, 0, 0, 0); const returnDate = new Date(item.returnDate); if (item.status !== "Сдано" && returnDate < today) { item.status = "Просрочено"; } return item; } function getStatusClass(status) { switch (status) { case "В носке": return "status-worn"; case "Сдано": return "status-returned"; case "Просрочено": return "status-overdue"; default: return "status-worn"; } } // Счётчики function updateCounts() { // Пересчитываем статусы перед подсчётом items = items.map(updateItemStatus); saveToStorage(); const total = items.length; const worn = items.filter(i => i.status === "В носке").length; const returned = items.filter(i => i.status === "Сдано").length; const overdue = items.filter(i => i.status === "Просрочено").length; document.getElementById("count-total").textContent = total; document.getElementById("count-worn").textContent = worn; document.getElementById("count-returned").textContent = returned; document.getElementById("count-overdue").textContent = overdue; } // Модальное окно function openModal(isEdit = false) { document.getElementById("modal").classList.remove("hidden"); document.getElementById("modal-title").textContent = isEdit ? "Редактирование выдачи" : "Новая выдача"; if (!isEdit) { document.getElementById("form").reset(); document.getElementById("edit-id").value = ""; // Устанавливаем сегодняшнюю дату по умолчанию document.getElementById("form-issue-date").value = new Date().toISOString().split("T")[0]; } } function closeModal() { document.getElementById("modal").classList.add("hidden"); } // Сохранение (добавление/редактирование) function saveItem(event) { event.preventDefault(); const id = document.getElementById("edit-id").value; const fio = document.getElementById("form-fio").value.trim(); const item = document.getElementById("form-item").value.trim(); const issueDate = document.getElementById("form-issue-date").value; const returnDate = document.getElementById("form-return-date").value; if (id) { // Редактирование const idx = items.findIndex(i => i.id == id); if (idx !== -1) { const oldItem = { ...items[idx] }; items[idx] = { ...items[idx], fio, item, issueDate, returnDate }; logs.unshift({ type: "edit", message: `Изменено: ${oldItem.fio} — ${oldItem.item}`, timestamp: new Date().toISOString() }); } } else { // Добавление const newId = Date.now(); let status = "В носке"; const today = new Date(); today.setHours(0, 0, 0, 0); const retDate = new Date(returnDate); if (retDate < today) status = "Просрочено"; items.unshift({ id: newId, fio, item, issueDate, returnDate, status }); logs.unshift({ type: "add", message: `Добавлено: ${fio} — ${item}`, timestamp: new Date().toISOString() }); } saveToStorage(); saveLogToStorage(); closeModal(); renderTable(); renderLog(); } // Редактирование function editItem(id) { const item = items.find(i => i.id === id); if (!item) return; document.getElementById("edit-id").value = item.id; document.getElementById("form-fio").value = item.fio; document.getElementById("form-item").value = item.item; document.getElementById("form-issue-date").value = item.issueDate; document.getElementById("form-return-date").value = item.returnDate; openModal(true); } // Удаление function deleteItem(id) { const item = items.find(i => i.id === id); if (!item) return; if (confirm(`Вы уверены, что хотите удалить запись:\n${item.fio} — ${item.item}?`)) { items = items.filter(i => i.id !== id); logs.unshift({ type: "delete", message: `Удалено: ${item.fio} — ${item.item}`, timestamp: new Date().toISOString() }); saveToStorage(); saveLogToStorage(); renderTable(); renderLog(); } } // Журнал изменений function renderLog() { const container = document.getElementById("log-container"); if (logs.length === 0) { container.innerHTML = '
История пуста
'; return; } container.innerHTML = logs.map(log => { const date = new Date(log.timestamp); const dateStr = date.toLocaleDateString("ru-RU") + " " + date.toLocaleTimeString("ru-RU", { hour: "2-digit", minute: "2-digit" }); return `
${log.message} (${dateStr})
`; }).join(""); } // Выгрузка в Excel (CSV с BOM) function exportToExcel() { const head = ["№", "ФИО", "Наименование", "Дата выдачи", "Дата возврата", "Статус"]; const rows = items.map((item, idx) => [ idx + 1, item.fio, item.item, formatDate(item.issueDate), formatDate(item.returnDate), item.status ]); const csvContent = "\uFEFF" + [ head.join(";"), ...rows.map(r => r.map(v => `"${String(v).replace(/"/g, '""')}"`).join(";")) ].join("\n"); const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" }); const link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = `zhurnal_${new Date().toISOString().slice(0, 10)}.csv`; link.click(); } // Утилиты function formatDate(dateStr) { if (!dateStr) return ""; const [year, month, day] = dateStr.split("-"); return `${day}.${month}.${year}`; } function escapeHtml(text) { const div = document.createElement("div"); div.textContent = text; return div.innerHTML; } // Закрытие модального окна по клику вне document.getElementById("modal").addEventListener("click", (e) => { if (e.target.id === "modal") closeModal(); });