index.pug 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. div(class="admin-products")
  2. div(class="admin-products__header")
  3. h1(class="admin-products__title") Управление товарами
  4. div(class="admin-products__actions")
  5. button(
  6. @click="showProductModal = true"
  7. class="admin-products__btn admin-products__btn--primary"
  8. ) Добавить товар
  9. button(
  10. @click="showImportModal = true"
  11. class="admin-products__btn admin-products__btn--secondary"
  12. ) Импорт из CSV
  13. button(
  14. @click="showCategoriesModal = true"
  15. class="admin-products__btn admin-products__btn--secondary"
  16. ) Управление категориями
  17. button(
  18. @click="showMassActionsModal = true"
  19. class="admin-products__btn admin-products__btn--primary"
  20. ) Массовые действия
  21. div(class="admin-products__content")
  22. div(class="admin-products__filters")
  23. div(class="admin-products__filter-group")
  24. label(class="admin-products__label") Поиск
  25. input(
  26. v-model="searchQuery"
  27. type="text"
  28. class="admin-products__input"
  29. placeholder="Название или артикул..."
  30. )
  31. div(class="admin-products__filter-group")
  32. label(class="admin-products__label") Категория
  33. select(v-model="selectedCategory" class="admin-products__select")
  34. option(value="") Все категории
  35. option(
  36. v-for="category in categories"
  37. :key="category._id"
  38. :value="category._id"
  39. ) {{ category.name }}
  40. div(class="admin-products__filter-group")
  41. label(class="admin-products__label") Статус
  42. select(v-model="selectedStatus" class="admin-products__select")
  43. option(value="") Все
  44. option(value="active") Активные
  45. option(value="inactive") Неактивные
  46. div(class="admin-products__mass-actions")
  47. div(class="admin-products__mass-header")
  48. div(class="admin-products__selection-info")
  49. span Выбрано товаров: {{ selectedProducts.length }}
  50. button(
  51. v-if="selectedProducts.length > 0"
  52. @click="clearSelection"
  53. class="admin-products__btn admin-products__btn--secondary"
  54. ) Сбросить
  55. div(class="admin-products__mass-buttons")
  56. button(
  57. @click="activateSelected"
  58. :disabled="selectedProducts.length === 0"
  59. class="admin-products__btn admin-products__btn--secondary"
  60. ) Активировать
  61. button(
  62. @click="deactivateSelected"
  63. :disabled="selectedProducts.length === 0"
  64. class="admin-products__btn admin-products__btn--secondary"
  65. ) Деактивировать
  66. button(
  67. @click="deleteSelected"
  68. :disabled="selectedProducts.length === 0"
  69. class="admin-products__btn admin-products__btn--danger"
  70. ) Удалить
  71. button(
  72. @click="showCategoryAssignModal = true"
  73. :disabled="selectedProducts.length === 0"
  74. class="admin-products__btn admin-products__btn--primary"
  75. ) Назначить категорию
  76. div(class="admin-products__list")
  77. div(class="admin-products__table-container")
  78. table(class="admin-products__table")
  79. thead
  80. tr
  81. th(class="admin-products__th admin-products__th--checkbox")
  82. input(
  83. type="checkbox"
  84. v-model="selectAll"
  85. @change="toggleSelectAll"
  86. class="admin-products__checkbox"
  87. )
  88. th(class="admin-products__th") Изобр.
  89. th(class="admin-products__th") Название
  90. th(class="admin-products__th") Артикул
  91. th(class="admin-products__th") Цена
  92. th(class="admin-products__th") Категория
  93. th(class="admin-products__th") Статус
  94. th(class="admin-products__th") Действия
  95. tbody
  96. tr(
  97. v-for="product in filteredProducts"
  98. :key="product._id"
  99. class="admin-products__tr"
  100. :class="{'admin-products__tr--selected': isProductSelected(product._id)}"
  101. )
  102. td(class="admin-products__td admin-products__td--checkbox")
  103. input(
  104. type="checkbox"
  105. :value="product._id"
  106. v-model="selectedProducts"
  107. class="admin-products__checkbox"
  108. )
  109. td(class="admin-products__td")
  110. img(
  111. v-if="product.image"
  112. :src="product.image"
  113. :alt="product.name"
  114. class="admin-products__image"
  115. )
  116. div(v-else class="admin-products__no-image") Нет
  117. td(class="admin-products__td")
  118. div(class="admin-products__name") {{ product.name }}
  119. td(class="admin-products__td") {{ product.sku }}
  120. td(class="admin-products__td")
  121. div(class="admin-products__price") {{ formatPrice(product.price) }}
  122. div(
  123. v-if="product.oldPrice"
  124. class="admin-products__old-price"
  125. ) {{ formatPrice(product.oldPrice) }}
  126. td(class="admin-products__td") {{ getCategoryName(product.category) }}
  127. td(class="admin-products__td")
  128. span(
  129. :class="getStatusClass(product.active)"
  130. ) {{ product.active ? 'Активен' : 'Неактивен' }}
  131. td(class="admin-products__td")
  132. div(class="admin-products__action-buttons")
  133. button(
  134. @click="editProduct(product)"
  135. class="admin-products__action-btn admin-products__action-btn--edit"
  136. ) Редакт.
  137. button(
  138. @click="toggleProductStatus(product)"
  139. class="admin-products__action-btn admin-products__action-btn--toggle"
  140. ) {{ product.active ? 'Выкл.' : 'Вкл.' }}
  141. button(
  142. @click="deleteProduct(product._id)"
  143. class="admin-products__action-btn admin-products__action-btn--delete"
  144. ) Удалить
  145. // Модальное окно массового назначения категории
  146. div(v-if="showCategoryAssignModal" class="admin-products__modal")
  147. div(class="admin-products__modal-content")
  148. h3(class="admin-products__modal-title") Назначить категорию для {{ selectedProducts.length }} товаров
  149. div(class="admin-products__modal-form")
  150. div(class="admin-products__form-group")
  151. label(class="admin-products__label") Категория
  152. select(v-model="massCategory" class="admin-products__select")
  153. option(value="") Без категории
  154. option(
  155. v-for="category in categories"
  156. :key="category._id"
  157. :value="category._id"
  158. ) {{ category.name }}
  159. div(class="admin-products__form-group")
  160. label(class="admin-products__checkbox-label")
  161. input(
  162. v-model="removeExistingCategories"
  163. type="checkbox"
  164. class="admin-products__checkbox"
  165. )
  166. span Удалить существующие категории
  167. div(class="admin-products__modal-actions")
  168. button(
  169. @click="assignCategoryToSelected"
  170. :disabled="!massCategory"
  171. class="admin-products__btn admin-products__btn--primary"
  172. ) Назначить
  173. button(
  174. @click="showCategoryAssignModal = false"
  175. class="admin-products__btn admin-products__btn--secondary"
  176. ) Отмена
  177. // Модальное окно массовых действий
  178. div(v-if="showMassActionsModal" class="admin-products__modal")
  179. div(class="admin-products__modal-content")
  180. h3(class="admin-products__modal-title") Массовые действия с товарами
  181. div(class="admin-products__mass-actions-grid")
  182. div(class="admin-products__mass-action")
  183. h4(class="admin-products__mass-action-title") Изменение статуса
  184. div(class="admin-products__mass-action-buttons")
  185. button(
  186. @click="massChangeStatus(true)"
  187. class="admin-products__btn admin-products__btn--secondary"
  188. ) Активировать все товары
  189. button(
  190. @click="massChangeStatus(false)"
  191. class="admin-products__btn admin-products__btn--secondary"
  192. ) Деактивировать все товары
  193. div(class="admin-products__mass-action")
  194. h4(class="admin-products__mass-action-title") Управление категориями
  195. div(class="admin-products__mass-action-buttons")
  196. button(
  197. @click="showMassCategoryAssign = true"
  198. class="admin-products__btn admin-products__btn--secondary"
  199. ) Назначить категорию всем
  200. button(
  201. @click="massRemoveCategories"
  202. class="admin-products__btn admin-products__btn--danger"
  203. ) Удалить все категории
  204. div(class="admin-products__mass-action")
  205. h4(class="admin-products__mass-action-title") Цены
  206. div(class="admin-products__mass-action-buttons")
  207. button(
  208. @click="showMassPriceModal = true"
  209. class="admin-products__btn admin-products__btn--secondary"
  210. ) Массовое изменение цен
  211. div(class="admin-products__mass-action")
  212. h4(class="admin-products__mass-action-title") Экспорт
  213. div(class="admin-products__mass-action-buttons")
  214. button(
  215. @click="exportProducts"
  216. class="admin-products__btn admin-products__btn--primary"
  217. ) Экспорт в CSV
  218. button(
  219. @click="exportSelectedProducts"
  220. :disabled="selectedProducts.length === 0"
  221. class="admin-products__btn admin-products__btn--primary"
  222. ) Экспорт выбранных
  223. div(class="admin-products__modal-actions")
  224. button(
  225. @click="showMassActionsModal = false"
  226. class="admin-products__btn admin-products__btn--secondary"
  227. ) Закрыть
  228. // Модальное окно массового назначения категории всем товарам
  229. div(v-if="showMassCategoryAssign" class="admin-products__modal")
  230. div(class="admin-products__modal-content")
  231. h3(class="admin-products__modal-title") Назначить категорию всем товарам
  232. div(class="admin-products__modal-form")
  233. div(class="admin-products__form-group")
  234. label(class="admin-products__label") Категория
  235. select(v-model="massAllCategory" class="admin-products__select")
  236. option(value="") Без категории
  237. option(
  238. v-for="category in categories"
  239. :key="category._id"
  240. :value="category._id"
  241. ) {{ category.name }}
  242. div(class="admin-products__form-group")
  243. label(class="admin-products__checkbox-label")
  244. input(
  245. v-model="massRemoveAllCategories"
  246. type="checkbox"
  247. class="admin-products__checkbox"
  248. )
  249. span Удалить существующие категории у всех товаров
  250. div(class="admin-products__modal-actions")
  251. button(
  252. @click="assignCategoryToAll"
  253. :disabled="!massAllCategory"
  254. class="admin-products__btn admin-products__btn--primary"
  255. ) Назначить всем
  256. button(
  257. @click="showMassCategoryAssign = false"
  258. class="admin-products__btn admin-products__btn--secondary"
  259. ) Отмена
  260. // Модальное окно массового изменения цен
  261. div(v-if="showMassPriceModal" class="admin-products__modal")
  262. div(class="admin-products__modal-content")
  263. h3(class="admin-products__modal-title") Массовое изменение цен
  264. div(class="admin-products__modal-form")
  265. div(class="admin-products__form-group")
  266. label(class="admin-products__label") Тип изменения
  267. select(v-model="priceChangeType" class="admin-products__select")
  268. option(value="fixed") Фиксированная цена
  269. option(value="percent") Изменить на процент
  270. option(value="increase") Увеличить на сумму
  271. option(value="decrease") Уменьшить на сумму
  272. div(class="admin-products__form-group")
  273. label(class="admin-products__label") Значение
  274. input(
  275. v-model="priceChangeValue"
  276. type="number"
  277. class="admin-products__input"
  278. placeholder="Введите значение"
  279. step="0.01"
  280. )
  281. div(class="admin-products__form-group")
  282. label(class="admin-products__checkbox-label")
  283. input(
  284. v-model="applyToOldPrice"
  285. type="checkbox"
  286. class="admin-products__checkbox"
  287. )
  288. span Применить к старой цене
  289. div(class="admin-products__modal-actions")
  290. button(
  291. @click="applyMassPriceChange"
  292. :disabled="!priceChangeValue"
  293. class="admin-products__btn admin-products__btn--primary"
  294. ) Применить
  295. button(
  296. @click="showMassPriceModal = false"
  297. class="admin-products__btn admin-products__btn--secondary"
  298. ) Отмена
  299. // Модальное окно редактирования товара
  300. div(v-if="showProductModal" class="admin-products__modal")
  301. div(class="admin-products__modal-content")
  302. h3(class="admin-products__modal-title") {{ editingProduct ? 'Редактирование' : 'Добавление' }} товара
  303. div(class="admin-products__modal-form")
  304. div(class="admin-products__form-group")
  305. label(class="admin-products__label") Название товара *
  306. input(
  307. v-model="productForm.name"
  308. type="text"
  309. class="admin-products__input"
  310. placeholder="Введите название товара"
  311. required
  312. )
  313. div(class="admin-products__form-group")
  314. label(class="admin-products__label") Артикул *
  315. input(
  316. v-model="productForm.sku"
  317. type="text"
  318. class="admin-products__input"
  319. placeholder="Артикул товара"
  320. required
  321. )
  322. div(class="admin-products__form-group")
  323. label(class="admin-products__label") Категория
  324. select(v-model="productForm.category" class="admin-products__select")
  325. option(value="") Выберите категорию
  326. option(
  327. v-for="category in categories"
  328. :key="category._id"
  329. :value="category._id"
  330. ) {{ category.name }}
  331. div(class="admin-products__form-group")
  332. label(class="admin-products__label") Цена *
  333. input(
  334. v-model="productForm.price"
  335. type="number"
  336. class="admin-products__input"
  337. placeholder="0.00"
  338. min="0"
  339. step="0.01"
  340. required
  341. )
  342. div(class="admin-products__form-group")
  343. label(class="admin-products__label") Старая цена
  344. input(
  345. v-model="productForm.oldPrice"
  346. type="number"
  347. class="admin-products__input"
  348. placeholder="0.00"
  349. min="0"
  350. step="0.01"
  351. )
  352. div(class="admin-products__form-group")
  353. label(class="admin-products__label") Бренд
  354. input(
  355. v-model="productForm.brand"
  356. type="text"
  357. class="admin-products__input"
  358. placeholder="Бренд производителя"
  359. )
  360. div(class="admin-products__form-group")
  361. label(class="admin-products__label") Описание
  362. textarea(
  363. v-model="productForm.description"
  364. class="admin-products__textarea"
  365. placeholder="Описание товара"
  366. rows="4"
  367. )
  368. div(class="admin-products__form-group")
  369. label(class="admin-products__label") Изображение товара
  370. div(class="admin-products__image-upload")
  371. div(v-if="productForm.image" class="admin-products__image-preview")
  372. img(:src="productForm.image" :alt="productForm.name" class="admin-products__preview-image")
  373. button(
  374. @click="removeProductImage"
  375. class="admin-products__btn admin-products__btn--danger"
  376. ) Удалить
  377. div(v-else class="admin-products__image-placeholder") Изображение не загружено
  378. input(
  379. type="file"
  380. ref="productImageInput"
  381. @change="onProductImageUpload"
  382. accept="image/*"
  383. class="admin-products__file-input"
  384. id="product-image-upload"
  385. )
  386. label(for="product-image-upload" class="admin-products__btn admin-products__btn--secondary") Выбрать изображение
  387. div(class="admin-products__form-group")
  388. label(class="admin-products__checkbox-label")
  389. input(
  390. v-model="productForm.active"
  391. type="checkbox"
  392. class="admin-products__checkbox"
  393. )
  394. span Активный товар
  395. div(class="admin-products__form-group")
  396. label(class="admin-products__label") Домены
  397. div(class="admin-products__domains-list")
  398. label(
  399. v-for="domain in availableDomains"
  400. :key="domain._id"
  401. class="admin-products__domain-label"
  402. )
  403. input(
  404. type="checkbox"
  405. :value="domain.domain"
  406. v-model="productForm.domains"
  407. class="admin-products__domain-checkbox"
  408. )
  409. span {{ domain.domain }}
  410. div(class="admin-products__modal-actions")
  411. button(
  412. @click="saveProduct"
  413. class="admin-products__btn admin-products__btn--primary"
  414. ) {{ editingProduct ? 'Обновить' : 'Создать' }}
  415. button(
  416. @click="showProductModal = false"
  417. class="admin-products__btn admin-products__btn--secondary"
  418. ) Отмена
  419. // Модальное окно импорта
  420. div(v-if="showImportModal" class="admin-products__modal")
  421. div(class="admin-products__modal-content")
  422. h3(class="admin-products__modal-title") Импорт товаров из CSV
  423. div(class="admin-products__import-form")
  424. div(class="admin-products__form-group")
  425. label(class="admin-products__label") Выберите CSV файл
  426. input(
  427. type="file"
  428. @change="onFileSelect"
  429. accept=".csv"
  430. class="admin-products__file-input"
  431. )
  432. p(class="admin-products__help-text") Поддерживается формат CSV с разделителем ; и кодировкой UTF-8
  433. div(v-if="selectedFile" class="admin-products__file-info")
  434. p Выбран файл: {{ selectedFile.name }}
  435. button(
  436. @click="importProducts"
  437. :disabled="importing"
  438. class="admin-products__btn admin-products__btn--primary"
  439. ) {{ importing ? 'Импорт...' : 'Начать импорт' }}
  440. div(v-if="importResults" class="admin-products__import-results")
  441. h4(v-if="importResults.success" class="admin-products__success") Импорт успешно завершен!
  442. h4(v-else class="admin-products__error") Ошибка импорта
  443. p Обработано товаров: {{ importResults.processed }}
  444. p(v-if="importResults.errors && importResults.errors.length")
  445. strong Ошибки:
  446. ul
  447. li(v-for="error in importResults.errors" :key="error") {{ error }}
  448. p(v-if="importResults.error") Ошибка: {{ importResults.error }}
  449. div(class="admin-products__modal-actions")
  450. button(
  451. @click="showImportModal = false"
  452. class="admin-products__btn admin-products__btn--secondary"
  453. ) Закрыть
  454. // Модальное окно управления категориями
  455. div(v-if="showCategoriesModal" class="admin-products__modal")
  456. div(class="admin-products__modal-content admin-products__modal-content--large")
  457. h3(class="admin-products__modal-title") Управление категориями
  458. div(class="admin-products__categories-tabs")
  459. button(
  460. @click="categoriesActiveTab = 'list'"
  461. :class="getCategoriesTabClass('list')"
  462. ) Список категорий
  463. button(
  464. @click="categoriesActiveTab = 'import'"
  465. :class="getCategoriesTabClass('import')"
  466. ) Импорт категорий
  467. // Список категорий
  468. div(v-if="categoriesActiveTab === 'list'" class="admin-products__categories-list")
  469. div(class="admin-products__categories-header")
  470. button(
  471. @click="showCategoryModal = true"
  472. class="admin-products__btn admin-products__btn--primary"
  473. ) Добавить категорию
  474. div(class="admin-products__categories-grid")
  475. div(
  476. v-for="category in categories"
  477. :key="category._id"
  478. class="admin-products__category-item"
  479. )
  480. div(class="admin-products__category-preview")
  481. img(
  482. v-if="category.image"
  483. :src="category.image"
  484. :alt="category.name"
  485. class="admin-products__category-image"
  486. )
  487. div(v-else class="admin-products__category-no-image") Нет изображения
  488. div(class="admin-products__category-info")
  489. h4(class="admin-products__category-name") {{ category.name }}
  490. p(class="admin-products__category-description") {{ category.description || 'Без описания' }}
  491. div(class="admin-products__category-meta")
  492. span(class="admin-products__category-products") Товаров: {{ getCategoryProductCount(category._id) }}
  493. span(
  494. :class="getStatusClass(category.active)"
  495. ) {{ category.active ? 'Активна' : 'Неактивна' }}
  496. div(class="admin-products__category-actions")
  497. button(
  498. @click="editCategory(category)"
  499. class="admin-products__btn admin-products__btn--edit"
  500. ) Редактировать
  501. button(
  502. @click="deleteCategory(category._id)"
  503. class="admin-products__btn admin-products__btn--delete"
  504. ) Удалить
  505. // Импорт категорий
  506. div(v-if="categoriesActiveTab === 'import'" class="admin-products__categories-import")
  507. div(class="admin-products__form-group")
  508. label(class="admin-products__label") Выберите CSV файл категорий
  509. input(
  510. type="file"
  511. @change="onCategoriesFileSelect"
  512. accept=".csv"
  513. class="admin-products__file-input"
  514. )
  515. p(class="admin-products__help-text") Формат CSV с полями: name, slug, description, parentCategory, sortOrder, active
  516. div(v-if="selectedCategoriesFile" class="admin-products__file-info")
  517. p Выбран файл: {{ selectedCategoriesFile.name }}
  518. button(
  519. @click="importCategories"
  520. :disabled="importingCategories"
  521. class="admin-products__btn admin-products__btn--primary"
  522. ) {{ importingCategories ? 'Импорт...' : 'Импорт категорий' }}
  523. div(v-if="categoriesImportResults" class="admin-products__import-results")
  524. h4(v-if="categoriesImportResults.success" class="admin-products__success") Импорт категорий завершен!
  525. h4(v-else class="admin-products__error") Ошибка импорта категорий
  526. p Обработано категорий: {{ categoriesImportResults.processed }}
  527. p(v-if="categoriesImportResults.errors && categoriesImportResults.errors.length")
  528. strong Ошибки:
  529. ul
  530. li(v-for="error in categoriesImportResults.errors" :key="error") {{ error }}
  531. div(class="admin-products__modal-actions")
  532. button(
  533. @click="showCategoriesModal = false"
  534. class="admin-products__btn admin-products__btn--secondary"
  535. ) Закрыть
  536. // Модальное окно редактирования категории
  537. div(v-if="showCategoryModal" class="admin-products__modal")
  538. div(class="admin-products__modal-content")
  539. h3(class="admin-products__modal-title") {{ editingCategory ? 'Редактирование' : 'Добавление' }} категории
  540. div(class="admin-products__modal-form")
  541. div(class="admin-products__form-group")
  542. label(class="admin-products__label") Название категории *
  543. input(
  544. v-model="categoryForm.name"
  545. type="text"
  546. class="admin-products__input"
  547. placeholder="Введите название категории"
  548. required
  549. )
  550. div(class="admin-products__form-group")
  551. label(class="admin-products__label") URL slug *
  552. input(
  553. v-model="categoryForm.slug"
  554. type="text"
  555. class="admin-products__input"
  556. placeholder="url-slug"
  557. required
  558. )
  559. div(class="admin-products__form-group")
  560. label(class="admin-products__label") Описание
  561. textarea(
  562. v-model="categoryForm.description"
  563. class="admin-products__textarea"
  564. placeholder="Описание категории"
  565. rows="3"
  566. )
  567. div(class="admin-products__form-group")
  568. label(class="admin-products__label") Родительская категория
  569. select(v-model="categoryForm.parentCategory" class="admin-products__select")
  570. option(value="") Без родительской категории
  571. option(
  572. v-for="cat in categories.filter(c => c._id !== editingCategory?._id)"
  573. :key="cat._id"
  574. :value="cat._id"
  575. ) {{ cat.name }}
  576. div(class="admin-products__form-group")
  577. label(class="admin-products__label") Порядок сортировки
  578. input(
  579. v-model="categoryForm.sortOrder"
  580. type="number"
  581. class="admin-products__input"
  582. placeholder="0"
  583. min="0"
  584. )
  585. div(class="admin-products__form-group")
  586. label(class="admin-products__label") Изображение категории
  587. div(class="admin-products__image-upload")
  588. div(v-if="categoryForm.image" class="admin-products__image-preview")
  589. img(:src="categoryForm.image" :alt="categoryForm.name" class="admin-products__preview-image")
  590. button(
  591. @click="removeCategoryImage"
  592. class="admin-products__btn admin-products__btn--danger"
  593. ) Удалить
  594. div(v-else class="admin-products__image-placeholder") Изображение не загружено
  595. input(
  596. type="file"
  597. ref="categoryImageInput"
  598. @change="onCategoryImageUpload"
  599. accept="image/*"
  600. class="admin-products__file-input"
  601. id="category-image-upload"
  602. )
  603. label(for="category-image-upload" class="admin-products__btn admin-products__btn--secondary") Выбрать изображение
  604. div(class="admin-products__form-group")
  605. label(class="admin-products__label") Иконка для меню
  606. div(class="admin-products__image-upload")
  607. div(v-if="categoryForm.icon" class="admin-products__image-preview admin-products__image-preview--small")
  608. img(:src="categoryForm.icon" :alt="categoryForm.name" class="admin-products__preview-image")
  609. button(
  610. @click="removeCategoryIcon"
  611. class="admin-products__btn admin-products__btn--danger"
  612. ) Удалить
  613. div(v-else class="admin-products__image-placeholder") Иконка не загружена
  614. input(
  615. type="file"
  616. ref="categoryIconInput"
  617. @change="onCategoryIconUpload"
  618. accept="image/*"
  619. class="admin-products__file-input"
  620. id="category-icon-upload"
  621. )
  622. label(for="category-icon-upload" class="admin-products__btn admin-products__btn--secondary") Выбрать иконку
  623. div(class="admin-products__form-group")
  624. label(class="admin-products__checkbox-label")
  625. input(
  626. v-model="categoryForm.active"
  627. type="checkbox"
  628. class="admin-products__checkbox"
  629. )
  630. span Активная категория
  631. div(class="admin-products__form-group")
  632. label(class="admin-products__label") Домены
  633. div(class="admin-products__domains-list")
  634. label(
  635. v-for="domain in availableDomains"
  636. :key="domain._id"
  637. class="admin-products__domain-label"
  638. )
  639. input(
  640. type="checkbox"
  641. :value="domain.domain"
  642. v-model="categoryForm.domains"
  643. class="admin-products__domain-checkbox"
  644. )
  645. span {{ domain.domain }}
  646. div(class="admin-products__modal-actions")
  647. button(
  648. @click="saveCategory"
  649. class="admin-products__btn admin-products__btn--primary"
  650. ) {{ editingCategory ? 'Обновить' : 'Создать' }}
  651. button(
  652. @click="showCategoryModal = false"
  653. class="admin-products__btn admin-products__btn--secondary"
  654. ) Отмена