// JavaScript для страницы каталога товаров class CatalogManager { constructor() { this.warehouse = new WarehouseManager(); this.currentItems = []; this.filteredItems = []; this.currentPage = 1; this.itemsPerPage = 12; this.currentView = 'grid'; this.filters = {}; this.init(); } init() { $(document).ready(() => { this.loadCatalog(); this.bindEvents(); this.initializeFilters(); }); } bindEvents() { // Поиск и фильтры $('#searchInput').on('input', (e) => this.handleSearch(e.target.value)); $('#categoryFilter').on('change', (e) => this.handleCategoryFilter(e.target.value)); $('#priceMin, #priceMax').on('input', () => this.handlePriceFilter()); $('#inStockFilter, #lowStockFilter').on('change', () => this.applyFilters()); $('#clearFiltersBtn').on('click', () => this.clearFilters()); // Переключение вида $('input[name="viewMode"]').on('change', (e) => { this.currentView = e.target.id === 'gridView' ? 'grid' : 'list'; this.renderCatalog(); }); // Модальные окна $('#saveItemBtn').on('click', () => this.addNewItem()); $('#updateItemBtn').on('click', () => this.updateItem()); // Экспорт $('#exportBtn').on('click', () => this.exportCatalog()); } // Загрузка каталога async loadCatalog() { try { this.showLoading(); // Загружаем товары this.currentItems = await this.warehouse.getAllItems(); // Загружаем категории const categories = await this.warehouse.getCategories(); this.populateCategoryFilters(categories); // Применяем фильтры и рендерим this.applyFilters(); this.updateStatistics(); this.hideLoading(); } catch (error) { console.error('Ошибка при загрузке каталога:', error); auth.showNotification('Ошибка при загрузке каталога', 'danger'); this.hideLoading(); } } // Инициализация фильтров initializeFilters() { // Устанавливаем значения по умолчанию this.filters = { search: '', category: '', minPrice: null, maxPrice: null, inStock: false, lowStock: false }; } // Заполнение фильтра категорий populateCategoryFilters(categories) { const categoryFilter = $('#categoryFilter'); const addItemCategory = $('#itemCategory'); const editItemCategory = $('#editItemCategory'); // Очищаем существующие опции (кроме первой) categoryFilter.find('option:not(:first)').remove(); addItemCategory.find('option:not(:first)').remove(); editItemCategory.find('option:not(:first)').remove(); // Добавляем категории categories.forEach(category => { const option = ``; categoryFilter.append(option); addItemCategory.append(option); editItemCategory.append(option); }); } // Обработка поиска handleSearch(query) { this.filters.search = query; this.applyFilters(); } // Обработка фильтра категории handleCategoryFilter(category) { this.filters.category = category; this.applyFilters(); } // Обработка фильтра цены handlePriceFilter() { this.filters.minPrice = $('#priceMin').val() ? parseFloat($('#priceMin').val()) : null; this.filters.maxPrice = $('#priceMax').val() ? parseFloat($('#priceMax').val()) : null; this.applyFilters(); } // Применение всех фильтров applyFilters() { this.filters.inStock = $('#inStockFilter').is(':checked'); this.filters.lowStock = $('#lowStockFilter').is(':checked'); // Фильтруем товары this.filteredItems = this.currentItems.filter(item => { // Поиск по названию, описанию и штрих-коду if (this.filters.search) { const searchQuery = this.filters.search.toLowerCase(); const matchesSearch = item.name.toLowerCase().includes(searchQuery) || item.description.toLowerCase().includes(searchQuery) || item.barcode.includes(searchQuery); if (!matchesSearch) return false; } // Фильтр по категории if (this.filters.category && item.category !== this.filters.category) { return false; } // Фильтр по цене if (this.filters.minPrice && item.price < this.filters.minPrice) { return false; } if (this.filters.maxPrice && item.price > this.filters.maxPrice) { return false; } // Фильтр по наличию if (this.filters.inStock && item.quantity <= 0) { return false; } // Фильтр по низкому запасу if (this.filters.lowStock && item.quantity > item.minQuantity) { return false; } return true; }); this.currentPage = 1; this.renderCatalog(); this.updateStatistics(); } // Очистка фильтров clearFilters() { $('#searchInput').val(''); $('#categoryFilter').val(''); $('#priceMin').val(''); $('#priceMax').val(''); $('#inStockFilter').prop('checked', false); $('#lowStockFilter').prop('checked', false); this.initializeFilters(); this.applyFilters(); } // Рендеринг каталога renderCatalog() { const container = $('#catalogContainer'); container.empty(); if (this.filteredItems.length === 0) { container.html(`

Товары не найдены

Попробуйте изменить параметры поиска или фильтры

`); return; } // Пагинация const totalPages = Math.ceil(this.filteredItems.length / this.itemsPerPage); const startIndex = (this.currentPage - 1) * this.itemsPerPage; const endIndex = startIndex + this.itemsPerPage; const pageItems = this.filteredItems.slice(startIndex, endIndex); // Рендерим товары pageItems.forEach(item => { const itemHtml = this.currentView === 'grid' ? this.createGridItem(item) : this.createListItem(item); container.append(itemHtml); }); // Рендерим пагинацию this.renderPagination(totalPages); } // Создание карточки товара (сетка) createGridItem(item) { const category = this.getCategoryInfo(item.category); const stockStatus = this.getStockStatus(item); return `
${item.name}

${item.description.substring(0, 60)}${item.description.length > 60 ? '...' : ''}

${category.name} ${stockStatus.text}
Цена
${item.price.toLocaleString()} ₽
Количество
${item.quantity} шт.
${auth.hasPermission('write') ? ` ` : ''}
`; } // Создание строки товара (список) createListItem(item) { const category = this.getCategoryInfo(item.category); const stockStatus = this.getStockStatus(item); return `
${item.name}
${item.description.substring(0, 50)}${item.description.length > 50 ? '...' : ''}
${category.name}
${item.price.toLocaleString()} ₽
${item.quantity} шт.
${stockStatus.text}
`; } // Рендеринг пагинации renderPagination(totalPages) { const pagination = $('#pagination'); pagination.empty(); if (totalPages <= 1) return; // Кнопка "Предыдущая" const prevDisabled = this.currentPage === 1 ? 'disabled' : ''; pagination.append(`
  • `); // Номера страниц const startPage = Math.max(1, this.currentPage - 2); const endPage = Math.min(totalPages, this.currentPage + 2); for (let i = startPage; i <= endPage; i++) { const active = i === this.currentPage ? 'active' : ''; pagination.append(`
  • ${i}
  • `); } // Кнопка "Следующая" const nextDisabled = this.currentPage === totalPages ? 'disabled' : ''; pagination.append(`
  • `); } // Переход на страницу goToPage(page) { this.currentPage = page; this.renderCatalog(); } // Обновление статистики updateStatistics() { const totalItems = this.filteredItems.length; const inStockItems = this.filteredItems.filter(item => item.quantity > 0).length; const lowStockItems = this.filteredItems.filter(item => item.quantity <= item.minQuantity).length; const categories = [...new Set(this.filteredItems.map(item => item.category))].length; $('#totalItemsCount').text(totalItems); $('#inStockCount').text(inStockItems); $('#lowStockCount').text(lowStockItems); $('#categoriesCount').text(categories); } // Получение информации о категории getCategoryInfo(categoryId) { const categories = [ { id: 'electronics', name: 'Электроника', icon: 'fas fa-laptop' }, { id: 'clothing', name: 'Одежда', icon: 'fas fa-tshirt' }, { id: 'tools', name: 'Инструменты', icon: 'fas fa-tools' }, { id: 'office', name: 'Офисные принадлежности', icon: 'fas fa-briefcase' }, { id: 'furniture', name: 'Мебель', icon: 'fas fa-couch' }, { id: 'books', name: 'Книги', icon: 'fas fa-book' } ]; return categories.find(cat => cat.id === categoryId) || { id: 'unknown', name: 'Неизвестная категория', icon: 'fas fa-box' }; } // Получение статуса запаса getStockStatus(item) { if (item.quantity === 0) { return { class: 'bg-danger', text: 'Нет в наличии' }; } else if (item.quantity <= item.minQuantity) { return { class: 'bg-warning', text: 'Заканчивается' }; } else { return { class: 'bg-success', text: 'В наличии' }; } } // Просмотр товара viewItem(itemId) { const item = this.currentItems.find(i => i.id === itemId); if (!item) return; // Здесь можно открыть модальное окно с подробной информацией auth.showNotification(`Просмотр товара: ${item.name}`, 'info'); } // Редактирование товара async editItem(itemId) { const item = this.currentItems.find(i => i.id === itemId); if (!item) return; // Заполняем форму редактирования $('#editItemId').val(item.id); $('#editItemName').val(item.name); $('#editItemCategory').val(item.category); $('#editItemPrice').val(item.price); $('#editItemQuantity').val(item.quantity); $('#editItemDescription').val(item.description); $('#editItemBarcode').val(item.barcode); $('#editItemLocation').val(item.location); $('#editItemSupplier').val(item.supplier); $('#editItemMinQuantity').val(item.minQuantity); // Открываем модальное окно $('#editItemModal').modal('show'); } // Обновление товара async updateItem() { const formData = this.getFormData('#editItemForm'); if (!this.validateForm(formData)) { return; } try { const itemId = parseInt(formData.editItemId); const updateData = { name: formData.editItemName, category: formData.editItemCategory, price: parseFloat(formData.editItemPrice), quantity: parseInt(formData.editItemQuantity), description: formData.editItemDescription || '', barcode: formData.editItemBarcode || '', location: formData.editItemLocation || '', supplier: formData.editItemSupplier || '', minQuantity: parseInt(formData.editItemMinQuantity) || 0 }; await this.warehouse.updateItem(itemId, updateData); // Обновляем локальные данные const itemIndex = this.currentItems.findIndex(i => i.id === itemId); if (itemIndex !== -1) { this.currentItems[itemIndex] = { ...this.currentItems[itemIndex], ...updateData }; } auth.showNotification('Товар успешно обновлен', 'success'); // Закрываем модальное окно и обновляем каталог $('#editItemModal').modal('hide'); this.applyFilters(); } catch (error) { console.error('Ошибка при обновлении товара:', error); auth.showNotification('Ошибка при обновлении товара', 'danger'); } } // Добавление нового товара async addNewItem() { const formData = this.getFormData('#addItemForm'); if (!this.validateForm(formData)) { return; } try { const newItem = await this.warehouse.addItem(formData); // Добавляем в локальные данные this.currentItems.push(newItem); auth.showNotification('Товар успешно добавлен', 'success'); // Закрываем модальное окно и обновляем каталог $('#addItemModal').modal('hide'); this.applyFilters(); // Очищаем форму $('#addItemForm')[0].reset(); } catch (error) { console.error('Ошибка при добавлении товара:', error); auth.showNotification('Ошибка при добавлении товара', 'danger'); } } // Удаление товара async deleteItem(itemId) { if (!confirm('Вы уверены, что хотите удалить этот товар?')) { return; } try { await this.warehouse.deleteItem(itemId); // Удаляем из локальных данных this.currentItems = this.currentItems.filter(i => i.id !== itemId); auth.showNotification('Товар успешно удален', 'success'); this.applyFilters(); } catch (error) { console.error('Ошибка при удалении товара:', error); auth.showNotification('Ошибка при удалении товара', 'danger'); } } // Получение данных формы getFormData(formSelector) { const form = $(formSelector); const formData = {}; form.find('input, select, textarea').each(function() { const field = $(this); const name = field.attr('id'); const value = field.val(); if (name) { formData[name] = value; } }); return formData; } // Валидация формы validateForm(formData) { const requiredFields = ['itemName', 'itemCategory', 'itemPrice', 'itemQuantity']; for (const field of requiredFields) { if (!formData[field] || formData[field].trim() === '') { auth.showNotification(`Поле "${this.getFieldLabel(field)}" обязательно для заполнения`, 'warning'); return false; } } // Проверка числовых значений if (formData.itemPrice && parseFloat(formData.itemPrice) < 0) { auth.showNotification('Цена не может быть отрицательной', 'warning'); return false; } if (formData.itemQuantity && parseInt(formData.itemQuantity) < 0) { auth.showNotification('Количество не может быть отрицательным', 'warning'); return false; } return true; } // Получение метки поля getFieldLabel(fieldName) { const labels = { 'itemName': 'Название товара', 'itemCategory': 'Категория', 'itemPrice': 'Цена', 'itemQuantity': 'Количество', 'editItemName': 'Название товара', 'editItemCategory': 'Категория', 'editItemPrice': 'Цена', 'editItemQuantity': 'Количество' }; return labels[fieldName] || fieldName; } // Экспорт каталога async exportCatalog() { try { const exportData = await this.warehouse.exportData('items'); // Создаем CSV let csv = exportData.headers.join(',') + '\n'; exportData.rows.forEach(row => { csv += row.map(cell => `"${cell}"`).join(',') + '\n'; }); // Скачиваем файл const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); const url = URL.createObjectURL(blob); link.setAttribute('href', url); link.setAttribute('download', `каталог_товаров_${new Date().toISOString().split('T')[0]}.csv`); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link); auth.showNotification('Каталог успешно экспортирован', 'success'); } catch (error) { console.error('Ошибка при экспорте:', error); auth.showNotification('Ошибка при экспорте каталога', 'danger'); } } // Показать индикатор загрузки showLoading() { $('#catalogContainer').html(`

    Загрузка каталога...

    `); } // Скрыть индикатор загрузки hideLoading() { // Загрузка завершается в renderCatalog() } } // Инициализация менеджера каталога const catalogManager = new CatalogManager();