index.pug 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. .admin-products
  2. .admin-products__header
  3. h1.admin-products__title Управление товарами
  4. .admin-products__actions
  5. button.admin-products__btn.admin-products__btn--primary(
  6. @click="showProductModal = true"
  7. ) Добавить товар
  8. button.admin-products__btn.admin-products__btn--secondary(
  9. @click="showImportModal = true"
  10. ) Импорт из CSV
  11. .admin-products__filters
  12. .admin-products__search
  13. input.admin-products__search-input(
  14. type="text"
  15. placeholder="Поиск по названию или артикулу..."
  16. v-model="searchQuery"
  17. )
  18. .admin-products__category-filter
  19. select.admin-products__category-select(v-model="selectedCategory")
  20. option(value="") Все категории
  21. option(
  22. v-for="category in categories"
  23. :value="category.slug"
  24. ) {{ category.name }}
  25. .admin-products__content
  26. .admin-products__table-container
  27. table.admin-products__table
  28. thead
  29. tr
  30. th.admin-products__th-checkbox
  31. input(
  32. type="checkbox"
  33. @change="toggleAllProducts"
  34. :checked="selectedProducts.length === filteredProducts.length"
  35. )
  36. th.admin-products__th Название
  37. th.admin-products__th Артикул
  38. th.admin-products__th Категория
  39. th.admin-products__th Цена
  40. th.admin-products__th Статус
  41. th.admin-products__th Действия
  42. tbody
  43. tr.admin-products__tr(
  44. v-for="product in filteredProducts"
  45. :key="product._id"
  46. )
  47. td.admin-products__td-checkbox
  48. input(
  49. type="checkbox"
  50. :value="product._id"
  51. v-model="selectedProducts"
  52. )
  53. td.admin-products__td {{ product.name }}
  54. td.admin-products__td {{ product.sku }}
  55. td.admin-products__td {{ product.category }}
  56. td.admin-products__td {{ product.price }} ₽
  57. td.admin-products__td
  58. span.admin-products__status(
  59. :class="{'admin-products__status--active': product.active, 'admin-products__status--inactive': !product.active}"
  60. ) {{ product.active ? 'Активен' : 'Неактивен' }}
  61. td.admin-products__td
  62. .admin-products__actions
  63. button.admin-products__action-btn.admin-products__action-btn--edit(
  64. @click="editProduct(product)"
  65. ) Редактировать
  66. button.admin-products__action-btn.admin-products__action-btn--delete(
  67. @click="deleteProduct(product)"
  68. ) Удалить
  69. .admin-products__empty(v-if="filteredProducts.length === 0")
  70. p.admin-products__empty-text Товары не найдены
  71. //- Модальное окно товара
  72. .admin-modal(v-if="showProductModal")
  73. .admin-modal__overlay(@click="showProductModal = false")
  74. .admin-modal__content
  75. .admin-modal__header
  76. h2.admin-modal__title {{ currentProduct._id ? 'Редактировать товар' : 'Добавить товар' }}
  77. button.admin-modal__close(@click="showProductModal = false") ×
  78. .admin-modal__body
  79. .admin-form
  80. .admin-form__group
  81. label.admin-form__label Название товара *
  82. input.admin-form__input(
  83. type="text"
  84. v-model="currentProduct.name"
  85. placeholder="Введите название товара"
  86. )
  87. .admin-form__group
  88. label.admin-form__label Артикул *
  89. input.admin-form__input(
  90. type="text"
  91. v-model="currentProduct.sku"
  92. placeholder="Введите артикул"
  93. )
  94. .admin-form__group
  95. label.admin-form__label Категория
  96. select.admin-form__select(v-model="currentProduct.category")
  97. option(value="") Выберите категорию
  98. option(
  99. v-for="category in categories"
  100. :value="category.slug"
  101. ) {{ category.name }}
  102. .admin-form__row
  103. .admin-form__group
  104. label.admin-form__label Цена *
  105. input.admin-form__input(
  106. type="number"
  107. v-model.number="currentProduct.price"
  108. placeholder="0.00"
  109. step="0.01"
  110. )
  111. .admin-form__group
  112. label.admin-form__label Старая цена
  113. input.admin-form__input(
  114. type="number"
  115. v-model.number="currentProduct.oldPrice"
  116. placeholder="0.00"
  117. step="0.01"
  118. )
  119. .admin-form__group
  120. label.admin-form__label Описание
  121. textarea.admin-form__textarea(
  122. v-model="currentProduct.description"
  123. placeholder="Введите описание товара"
  124. rows="4"
  125. )
  126. .admin-form__group
  127. label.admin-form__label
  128. input.admin-form__checkbox(
  129. type="checkbox"
  130. v-model="currentProduct.active"
  131. )
  132. span Активный товар
  133. .admin-modal__footer
  134. button.admin-modal__btn.admin-modal__btn--secondary(
  135. @click="showProductModal = false"
  136. ) Отмена
  137. button.admin-modal__btn.admin-modal__btn--primary(
  138. @click="saveProductForm"
  139. ) Сохранить
  140. //- Модальное окно импорта
  141. .admin-modal(v-if="showImportModal")
  142. .admin-modal__overlay(@click="showImportModal = false")
  143. .admin-modal__content
  144. .admin-modal__header
  145. h2.admin-modal__title Импорт товаров из CSV
  146. button.admin-modal__close(@click="showImportModal = false") ×
  147. .admin-modal__body
  148. .admin-import
  149. .admin-import__upload
  150. input.admin-import__file-input(
  151. type="file"
  152. accept=".csv"
  153. @change="handleFileSelect"
  154. )
  155. .admin-import__upload-area(
  156. :class="{'admin-import__upload-area--dragover': dragOver}"
  157. @drop="handleDrop"
  158. @dragover="handleDragOver"
  159. @dragleave="dragOver = false"
  160. )
  161. p.admin-import__upload-text
  162. span Выберите CSV файл
  163. | или перетащите его сюда
  164. .admin-import__info(v-if="selectedFile")
  165. .admin-import__file-info
  166. span.admin-import__file-name {{ selectedFile.name }}
  167. span.admin-import__file-size ({{ (selectedFile.size / 1024).toFixed(2) }} KB)
  168. .admin-import__progress(v-if="importing")
  169. .admin-import__progress-bar
  170. .admin-import__progress-fill(:style="{width: importProgress + '%'}")
  171. .admin-import__progress-text {{ importProgress }}%
  172. .admin-import__results(v-if="importResults")
  173. .admin-import__result(
  174. :class="{'admin-import__result--success': importResults.success, 'admin-import__result--error': !importResults.success}"
  175. )
  176. h4.admin-import__result-title {{ importResults.success ? 'Импорт завершен' : 'Ошибка импорта' }}
  177. p.admin-import__result-text
  178. | Обработано: {{ importResults.processed }},
  179. | Успешно: {{ importResults.successful }},
  180. | С ошибками: {{ importResults.failed }}
  181. .admin-import__errors(v-if="importResults.errors && importResults.errors.length > 0")
  182. h5.admin-import__errors-title Ошибки:
  183. ul.admin-import__errors-list
  184. li.admin-import__error(
  185. v-for="error in importResults.errors"
  186. :key="error"
  187. ) {{ error }}
  188. .admin-modal__footer
  189. button.admin-modal__btn.admin-modal__btn--secondary(
  190. @click="showImportModal = false"
  191. :disabled="importing"
  192. ) Отмена
  193. button.admin-modal__btn.admin-modal__btn--primary(
  194. @click="importProducts"
  195. :disabled="!selectedFile || importing"
  196. ) {{ importing ? 'Импорт...' : 'Начать импорт' }}