Add files via upload

v0.0.3
This commit is contained in:
cyrteL
2025-07-28 17:31:27 +03:00
committed by GitHub
parent 119a74ad98
commit 4a6868ced6
17 changed files with 2395 additions and 292 deletions

403
js/categories.js Normal file
View File

@ -0,0 +1,403 @@
// JavaScript для управления категориями
class CategoryManager {
constructor() {
this.warehouse = new WarehouseManager();
this.categories = [];
this.currentCategory = null;
this.init();
}
async init() {
try {
// Проверяем авторизацию
if (!auth.isUserAuthenticated()) {
console.log('Пользователь не авторизован, перенаправление на login.html');
window.location.href = '../login.html';
return;
}
// Проверяем права доступа
if (!auth.hasRole('admin')) {
console.log('Пользователь не имеет прав администратора');
auth.showNotification('Недостаточно прав для доступа к этой странице', 'danger');
window.location.href = '../index.html';
return;
}
console.log('Инициализация управления категориями для администратора:', auth.getCurrentUser()?.name);
// Загружаем данные
await this.loadCategories();
this.updateStatistics();
this.renderCategoriesTable();
this.bindEvents();
// Загружаем категории в выпадающее меню
await this.loadCategoriesDropdown();
this.updateUserInfo();
} catch (error) {
console.error('Ошибка инициализации:', error);
auth.showNotification('Ошибка загрузки данных', 'danger');
}
}
// Загрузка категорий
async loadCategories() {
this.categories = await this.warehouse.getCategories();
}
// Обновление статистики
updateStatistics() {
const totalCategories = this.categories.length;
const activeCategories = this.categories.filter(cat => cat.active).length;
const emptyCategories = this.categories.filter(cat => cat.itemCount === 0).length;
// Получаем общее количество позиций
const allItems = this.warehouse.getAllItemsSync();
const totalItems = allItems.length;
$('#totalCategories').text(totalCategories);
$('#totalItems').text(totalItems);
$('#activeCategories').text(activeCategories);
$('#emptyCategories').text(emptyCategories);
}
// Рендеринг таблицы категорий
renderCategoriesTable() {
const tbody = $('#categoriesTable tbody');
tbody.empty();
if (this.categories.length === 0) {
tbody.append(`
<tr>
<td colspan="7" class="text-center py-4">
<div class="empty-state">
<i class="fas fa-tags fa-3x text-muted mb-3"></i>
<h5>Категории не найдены</h5>
<p class="text-muted">Добавьте первую категорию для начала работы</p>
</div>
</td>
</tr>
`);
return;
}
this.categories.forEach(category => {
const row = this.createCategoryRow(category);
tbody.append(row);
});
}
// Создание строки категории
createCategoryRow(category) {
const statusBadge = category.active ?
'<span class="badge bg-success">Активна</span>' :
'<span class="badge bg-secondary">Неактивна</span>';
const iconPreview = category.icon ?
`<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>` :
'<i class="fas fa-tag text-muted"></i>';
return `
<tr data-category-id="${category.id}">
<td>${category.id}</td>
<td>
<div class="d-flex align-items-center">
<span class="me-2">${iconPreview}</span>
<strong>${category.name}</strong>
</div>
</td>
<td>${category.description || '-'}</td>
<td>
<code>${category.icon || 'fas fa-tag'}</code>
</td>
<td>
<span class="badge bg-info">${category.itemCount || 0}</span>
</td>
<td>${statusBadge}</td>
<td>
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-primary" onclick="categoryManager.editCategory('${category.id}')" title="Редактировать">
<i class="fas fa-edit"></i>
</button>
<button class="btn btn-outline-danger" onclick="categoryManager.deleteCategory('${category.id}')" title="Удалить">
<i class="fas fa-trash"></i>
</button>
</div>
</td>
</tr>
`;
}
// Привязка событий
bindEvents() {
// Добавление категории
$('#saveCategoryBtn').on('click', () => this.addCategory());
// Редактирование категории
$('#updateCategoryBtn').on('click', () => this.updateCategory());
// Очистка формы при закрытии модального окна
$('#addCategoryModal').on('hidden.bs.modal', () => this.clearAddForm());
$('#editCategoryModal').on('hidden.bs.modal', () => this.clearEditForm());
// Валидация формы
$('#addCategoryForm').on('submit', (e) => {
e.preventDefault();
this.addCategory();
});
$('#editCategoryForm').on('submit', (e) => {
e.preventDefault();
this.updateCategory();
});
}
// Добавление категории
async addCategory() {
try {
const formData = this.getAddFormData();
if (!formData.name.trim()) {
auth.showNotification('Введите название категории', 'warning');
return;
}
// Проверяем уникальность названия
const existingCategory = this.categories.find(cat =>
cat.name.toLowerCase() === formData.name.toLowerCase()
);
if (existingCategory) {
auth.showNotification('Категория с таким названием уже существует', 'warning');
return;
}
const newCategory = await this.warehouse.addCategory(formData);
this.categories.push(newCategory);
this.updateStatistics();
this.renderCategoriesTable();
$('#addCategoryModal').modal('hide');
auth.showNotification('Категория успешно добавлена', 'success');
} catch (error) {
console.error('Ошибка при добавлении категории:', error);
auth.showNotification('Ошибка при добавлении категории', 'danger');
}
}
// Редактирование категории
async editCategory(categoryId) {
try {
const category = this.categories.find(cat => cat.id === categoryId);
if (!category) {
auth.showNotification('Категория не найдена', 'danger');
return;
}
this.currentCategory = category;
this.fillEditForm(category);
$('#editCategoryModal').modal('show');
} catch (error) {
console.error('Ошибка при редактировании категории:', error);
auth.showNotification('Ошибка при загрузке категории', 'danger');
}
}
// Обновление категории
async updateCategory() {
try {
if (!this.currentCategory) {
auth.showNotification('Категория не выбрана', 'warning');
return;
}
const formData = this.getEditFormData();
if (!formData.name.trim()) {
auth.showNotification('Введите название категории', 'warning');
return;
}
// Проверяем уникальность названия (исключая текущую категорию)
const existingCategory = this.categories.find(cat =>
cat.id !== this.currentCategory.id &&
cat.name.toLowerCase() === formData.name.toLowerCase()
);
if (existingCategory) {
auth.showNotification('Категория с таким названием уже существует', 'warning');
return;
}
const updatedCategory = await this.warehouse.updateCategory(this.currentCategory.id, formData);
// Обновляем категорию в списке
const index = this.categories.findIndex(cat => cat.id === this.currentCategory.id);
if (index !== -1) {
this.categories[index] = updatedCategory;
}
this.updateStatistics();
this.renderCategoriesTable();
$('#editCategoryModal').modal('hide');
auth.showNotification('Категория успешно обновлена', 'success');
} catch (error) {
console.error('Ошибка при обновлении категории:', error);
auth.showNotification('Ошибка при обновлении категории', 'danger');
}
}
// Удаление категории
async deleteCategory(categoryId) {
try {
const category = this.categories.find(cat => cat.id === categoryId);
if (!category) {
auth.showNotification('Категория не найдена', 'danger');
return;
}
// Проверяем, есть ли позиции в этой категории
if (category.itemCount > 0) {
const confirmDelete = confirm(
`В категории "${category.name}" есть ${category.itemCount} позиций. ` +
'Удаление категории приведет к удалению всех позиций. Продолжить?'
);
if (!confirmDelete) {
return;
}
} else {
const confirmDelete = confirm(`Вы уверены, что хотите удалить категорию "${category.name}"?`);
if (!confirmDelete) {
return;
}
}
await this.warehouse.deleteCategory(categoryId);
// Удаляем категорию из списка
this.categories = this.categories.filter(cat => cat.id !== categoryId);
this.updateStatistics();
this.renderCategoriesTable();
auth.showNotification('Категория успешно удалена', 'success');
} catch (error) {
console.error('Ошибка при удалении категории:', error);
auth.showNotification('Ошибка при удалении категории', 'danger');
}
}
// Получение данных формы добавления
getAddFormData() {
return {
name: $('#categoryName').val().trim(),
description: $('#categoryDescription').val().trim(),
icon: $('#categoryIcon').val().trim() || 'fas fa-tag',
color: $('#categoryColor').val(),
active: $('#categoryActive').is(':checked')
};
}
// Получение данных формы редактирования
getEditFormData() {
return {
name: $('#editCategoryName').val().trim(),
description: $('#editCategoryDescription').val().trim(),
icon: $('#editCategoryIcon').val().trim() || 'fas fa-tag',
color: $('#editCategoryColor').val(),
active: $('#editCategoryActive').is(':checked')
};
}
// Заполнение формы редактирования
fillEditForm(category) {
$('#editCategoryId').val(category.id);
$('#editCategoryName').val(category.name);
$('#editCategoryDescription').val(category.description || '');
$('#editCategoryIcon').val(category.icon || 'fas fa-tag');
$('#editCategoryColor').val(category.color || '#2c5aa0');
$('#editCategoryActive').prop('checked', category.active);
}
// Очистка формы добавления
clearAddForm() {
$('#addCategoryForm')[0].reset();
$('#categoryColor').val('#2c5aa0');
$('#categoryActive').prop('checked', true);
}
// Очистка формы редактирования
clearEditForm() {
$('#editCategoryForm')[0].reset();
$('#editCategoryColor').val('#2c5aa0');
this.currentCategory = null;
}
// Обновление информации о пользователе
updateUserInfo() {
const user = auth.getCurrentUser();
if (user) {
$('#currentUserInfo').text(user.name);
$('#loginLink').hide();
$('#profileDropdown').show();
$('#adminDropdown').show();
} else {
$('#currentUserInfo').text('Гость');
$('#loginLink').show();
$('#profileDropdown').hide();
$('#adminDropdown').hide();
}
}
// Загрузка категорий в выпадающее меню
async loadCategoriesDropdown() {
try {
const categories = await this.warehouse.getCategories();
const dropdown = $('#catalogCategoriesDropdown');
// Очищаем существующие категории (кроме "Все позиции" и разделителя)
dropdown.find('li:not(:first-child):not(:nth-child(2))').remove();
// Добавляем активные категории
categories.forEach(category => {
if (category.active) {
const categoryLink = `
<li>
<a class="dropdown-item" href="../catalog.html?category=${category.id}" title="${category.description || ''}">
<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>
${category.name}
</a>
</li>
`;
dropdown.append(categoryLink);
}
});
} catch (error) {
console.error('Ошибка загрузки категорий в выпадающее меню:', error);
}
}
}
// Инициализация при загрузке страницы
let categoryManager;
$(document).ready(() => {
categoryManager = new CategoryManager();
// Обработка выхода
$('#logoutBtn').on('click', (e) => {
e.preventDefault();
auth.logout();
window.location.href = '../login.html';
});
});