`;
} else if (status === 'deleted') {
// Для удаленных категорий показываем кнопку восстановления
categoriesListBody.innerHTML += `
${escapeHtml(category.title)}
${badge}
${escapeHtml(category.description)}
`;
} else {
// Для остальных категорий (unchanged, edited) показываем обычные кнопки
categoriesListBody.innerHTML += `
${escapeHtml(category.title)}
${badge}
${escapeHtml(category.description)}
${category.created_at ? new Date(category.created_at).toLocaleDateString('ru-RU') : 'Новая'}
${category.updated_at ? new Date(category.updated_at).toLocaleDateString('ru-RU') : 'Новая'}
`;
}
});
}
// Функция для экранирования HTML
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// Функции для работы с категориями
modal.editCategory = function (index) {
// Сохраняем оригинальные данные если еще не сохранены
if (!categories[index].originalData) {
categories[index].originalData = {
title: categories[index].title,
description: categories[index].description
};
}
// Создаем модальное окно для редактирования
const editModal = document.createElement('div');
editModal.className = 'modal fade';
editModal.id = 'editCategoryModal';
editModal.innerHTML = `
Редактирование категории
`;
document.body.appendChild(editModal);
const bsEditModal = new bootstrap.Modal(editModal);
// Обработчик сохранения изменений
editModal.querySelector('#saveEditCategoryBtn').addEventListener('click', () => {
const titleInput = editModal.querySelector('#editCategoryTitle');
const descriptionInput = editModal.querySelector('#editCategoryDescription');
const title = titleInput.value.trim();
const description = descriptionInput.value.trim();
// Валидация
if (!title || title.length < 2) {
showInfo('Название категории должно содержать минимум 2 символа', 'error');
titleInput.focus();
return;
}
if (!description || description.length < 2) {
showInfo('Описание категории должно содержать минимум 2 символа', 'error');
descriptionInput.focus();
return;
}
// Проверяем уникальность названия среди других категорий
const duplicate = categories.find((cat, i) =>
i !== index &&
cat.id !== categories[index].id &&
cat.title.toLowerCase() === title.toLowerCase() &&
cat.status !== 'deleted'
);
if (duplicate) {
showInfo('Категория с таким названием уже существует', 'error');
titleInput.focus();
return;
}
// Обновляем данные категории
categories[index].title = title;
categories[index].description = description;
categories[index].status = 'edited';
// Добавляем в изменения, если это существующая категория
if (categories[index].id) {
const updateIndex = changes.update.findIndex(item => item.id === categories[index].id);
if (updateIndex === -1) {
changes.update.push({
id: categories[index].id,
title: title,
description: description
});
} else {
changes.update[updateIndex] = {
id: categories[index].id,
title: title,
description: description
};
}
}
bsEditModal.hide();
setTimeout(() => {
editModal.remove();
renderCategoriesList();
updateChangesPanel();
showInfo('Изменения сохранены', 'success');
}, 300);
});
// Очистка при закрытии модалки
editModal.addEventListener('hidden.bs.modal', () => {
setTimeout(() => {
if (editModal.parentNode) editModal.remove();
}, 300);
});
bsEditModal.show();
setTimeout(() => {
editModal.querySelector('#editCategoryTitle').focus();
}, 100);
};
modal.cancelEditCategoryAction = function (index) {
if (categories[index].originalData) {
// Восстанавливаем исходные данные
categories[index].title = categories[index].originalData.title;
categories[index].description = categories[index].originalData.description;
categories[index].status = 'unchanged';
categories[index].originalData = null;
// Удаляем из изменений
if (categories[index].id) {
const updateIndex = changes.update.findIndex(item => item.id === categories[index].id);
if (updateIndex !== -1) {
changes.update.splice(updateIndex, 1);
}
}
renderCategoriesList();
updateChangesPanel();
showInfo('Изменения отменены', 'info');
}
};
modal.deleteCategory = function (index) {
// Сохраняем оригинальные данные если еще не сохранены
if (!categories[index].originalData) {
categories[index].originalData = {
title: categories[index].title,
description: categories[index].description
};
}
// Создаем модальное окно подтверждения удаления
const deleteModal = document.createElement('div');
deleteModal.className = 'modal fade';
deleteModal.id = 'deleteCategoryModal';
deleteModal.innerHTML = `
Удаление категории
Внимание! Категория может быть удалена только если в ней нет инструментов.
При попытке удаления категории, используемой в инструментах, вы получите увдомление об успехе,
при этом категория не будет удалена!
` : '';
}
// Переменная для хранения данных об остатках (будет загружена при раскрытии аккордеона)
let toolkitStocksData = null;
let isStocksLoading = false;
// Форматирование даты комментария
let commentDateInfo = '';
if (toolkitData.comment_at) {
const commentDate = new Date(toolkitData.comment_at);
commentDateInfo = `
Последнее изменение: ${commentDate.toLocaleDateString('ru-RU')} ${commentDate.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' })}
`;
} else {
commentDateInfo = `
Комментарии еще не оставляли
`;
}
// Информация о пользователе, оставившем комментарий
let commentUserInfo = '';
if (toolkitData.comment_user_data && toolkitData.comment_user_data.username) {
commentUserInfo = `
`;
// Рендерим основной контейнер с таблицей запросов
tabContent.innerHTML = `
Тип
Оформил
Со склада
На склад
Инструмент
Кол-во
Обоснование
Действия
Нет запросов по выбранным фильтрам
`;
// Функция для фильтрации запросов
function filterRequests() {
let filtered = requests;
// Фильтр по пользователю
if (currentFilters.user !== 'all') {
filtered = filtered.filter(r => r.init_user_id == currentFilters.user);
}
// Фильтр по типу действия
if (currentFilters.action !== 'all') {
filtered = filtered.filter(r => r.action === currentFilters.action);
}
return filtered;
}
// Функция для рендеринга строк таблицы
function renderRequestsTable() {
const tbody = document.getElementById(`${tabId}-requests-body`);
const noRequestsDiv = document.getElementById(`${tabId}-no-requests`);
const filteredRequests = filterRequests();
if (filteredRequests.length === 0) {
tbody.innerHTML = '';
noRequestsDiv.style.display = 'block';
return;
}
noRequestsDiv.style.display = 'none';
tbody.innerHTML = filteredRequests.map(request => {
// Определяем доступные действия
const actions = [];
// Кнопка отзыва (только для инициатора и неподтвержденных запросов)
if (request.init_user_id === userData.id && request.accepted === null) {
actions.push(`
`);
}
// Кнопки принятия/отклонения (в зависимости от прав)
let canDecide = false;
// Проверяем права в зависимости от типа запроса
if (request.action === 'Возврат' && accessData.refund_request_confirm) {
canDecide = true;
} else if (request.action === 'Списание' && accessData.debit_request_confirm) {
canDecide = true;
} else if (request.action !== 'Возврат' && request.action !== 'Списание' &&
(accessData.refund_request_confirm || accessData.debit_request_confirm)) {
// Для других типов запросов, если есть хотя бы одно из прав
console.warning('Unknown request action', request.action);
canDecide = true;
}
if (canDecide) {
actions.push(`
`);
}
// Если нет доступных действий
if (actions.length === 0) {
actions.push('Нет действий');
}
return `
` : ''}
`;
// Для инструментов добавляем дополнительные поля
if (actionData.specifications && Object.keys(actionData.specifications).length > 0) {
detailsHtml += `
Характеристики:
`;
detailsHtml += `
`;
for (const [key, value] of Object.entries(actionData.specifications)) {
detailsHtml += `
${key}: ${value}
`;
}
detailsHtml += `
`;
}
if (actionData.external_link) {
detailsHtml += `