document.head.insertAdjacentHTML('beforeend','')
PouchDB = require 'app/utils/pouch'
Papa = require 'papaparse'
module.exports =
name: 'AdminProducts'
render: (new Function '_ctx', '_cache', renderFns['app/pages/Admin/Products/index.pug'])()
data: ->
return {
products: []
categories: []
searchQuery: ''
selectedCategory: ''
selectedStatus: ''
showProductModal: false
showImportModal: false
editingProduct: null
selectedFile: null
importing: false
importResults: null
}
computed:
filteredProducts: ->
products = @products
# Фильтр по поиску
if @searchQuery
query = @searchQuery.toLowerCase()
products = products.filter (product) =>
product.name?.toLowerCase().includes(query) ||
product.sku?.toLowerCase().includes(query)
# Фильтр по категории
if @selectedCategory
products = products.filter (product) =>
product.category == @selectedCategory
# Фильтр по статусу
if @selectedStatus == 'active'
products = products.filter (product) => product.active
else if @selectedStatus == 'inactive'
products = products.filter (product) => !product.active
return products
methods:
loadProducts: ->
PouchDB.queryView('admin', 'products', { include_docs: true })
.then (result) =>
@products = result.rows.map (row) -> row.doc
.catch (error) =>
console.error 'Ошибка загрузки товаров:', error
@showNotification 'Ошибка загрузки товаров', 'error'
loadCategories: ->
PouchDB.queryView('admin', 'categories', { include_docs: true })
.then (result) =>
@categories = result.rows.map (row) -> row.doc
.catch (error) =>
console.error 'Ошибка загрузки категорий:', error
getCategoryName: (categoryId) ->
category = @categories.find (cat) -> cat._id == categoryId
category?.name || 'Без категории'
editProduct: (product) ->
@editingProduct = product
@showProductModal = true
toggleProductStatus: (product) ->
updatedProduct = {
...product
active: !product.active
updatedAt: new Date().toISOString()
}
PouchDB.saveToRemote(updatedProduct)
.then (result) =>
@loadProducts()
@showNotification 'Статус товара обновлен'
.catch (error) =>
console.error 'Ошибка обновления статуса:', error
@showNotification 'Ошибка обновления статуса', 'error'
deleteProduct: (productId) ->
if confirm('Вы уверены, что хотите удалить этот товар?')
PouchDB.getDocument(productId)
.then (doc) ->
PouchDB.saveToRemote({ ...doc, _deleted: true })
.then (result) =>
@loadProducts()
@showNotification 'Товар удален'
.catch (error) =>
console.error 'Ошибка удаления товара:', error
@showNotification 'Ошибка удаления товара', 'error'
onFileSelect: (event) ->
@selectedFile = event.target.files[0]
@importResults = null
importProducts: ->
if !@selectedFile
@showNotification 'Выберите файл для импорта', 'error'
return
@importing = true
@importResults = null
reader = new FileReader()
reader.onload = (e) =>
try
results = Papa.parse e.target.result, {
header: true
delimiter: ';'
skipEmptyLines: true
encoding: 'UTF-8'
}
products = results.data.filter (row) =>
row && row['Артикул*'] && row['Название товара'] && row['Цена, руб.*']
couchProducts = products.map (product, index) =>
@transformProductData(product, index)
# Пакетное сохранение
PouchDB.bulkDocs(couchProducts)
.then (result) =>
@importResults = { success: true, processed: couchProducts.length }
@importing = false
@loadProducts()
@showNotification "Импортировано #{couchProducts.length} товаров"
.catch (error) =>
@importResults = { success: false, error: error.message, processed: 0 }
@importing = false
@showNotification "Ошибка импорта: #{error.message}", 'error'
catch error
@importResults = { success: false, error: error.message, processed: 0 }
@importing = false
@showNotification "Ошибка обработки файла: #{error.message}", 'error'
reader.readAsText(@selectedFile, 'UTF-8')
transformProductData: (product, index) ->
# Базовые поля
productData = {
_id: "product:#{Date.now()}-#{index}"
type: 'product'
name: product['Название товара']
sku: product['Артикул*']
price: parseFloat(product['Цена, руб.*'].replace(/\s/g, '').replace(',', '.')) || 0
active: true
createdAt: new Date().toISOString()
updatedAt: new Date().toISOString()
}
# Дополнительные поля
if product['Цена до скидки, руб.']
productData.oldPrice = parseFloat(product['Цена до скидки, руб.'].replace(/\s/g, '').replace(',', '.'))
if product['Ссылка на главное фото*']
productData.image = product['Ссылка на главное фото*']
if product['Бренд*']
productData.brand = product['Бренд*']
if product['Тип*']
productData.productType = product['Тип*']
# Rich content преобразование
if product['Rich-контент JSON']
try
richContent = JSON.parse(product['Rich-контент JSON'])
productData.description = @richContentToMarkdown(richContent)
catch
productData.description = product['Аннотация'] || ''
else
productData.description = product['Аннотация'] || ''
# Домены (все товары доступны на всех доменах по умолчанию)
productData.domains = @availableDomains?.map((d) -> d.domain) || []
return productData
richContentToMarkdown: (richContent) ->
# Простое преобразование rich content в markdown
return JSON.stringify(richContent) # Временная реализация
formatPrice: (price) ->
return '0 ₽' if !price
new Intl.NumberFormat('ru-RU', {
style: 'currency'
currency: 'RUB'
minimumFractionDigits: 0
}).format(price)
getStatusClass: (isActive) ->
baseClass = 'admin-products__status'
if isActive
return "#{baseClass} admin-products__status--active"
else
return "#{baseClass} admin-products__status--inactive"
showNotification: (message, type = 'success') ->
@$root.showNotification?(message, type) || debug.log("#{type}: #{message}")
mounted: ->
@loadProducts()
@loadCategories()