diff --git a/frontend/admin.html b/frontend/admin.html
index feb9fc9..3d19e9a 100644
--- a/frontend/admin.html
+++ b/frontend/admin.html
@@ -1337,56 +1337,6 @@
|
-
-
diff --git a/frontend/js/admin/sections/shop.js b/frontend/js/admin/sections/shop.js
index bd18b57..7f86e9b 100644
--- a/frontend/js/admin/sections/shop.js
+++ b/frontend/js/admin/sections/shop.js
@@ -4,8 +4,6 @@
'use strict';
let inited = false;
let _shopItems = [];
- let _shopEditId = null;
- let _shopSaving = false;
async function load() {
try {
@@ -67,73 +65,120 @@
if (window.lucide) lucide.createIcons();
}
- function showShopForm() {
- const form = document.getElementById('shop-item-form');
- form.style.display = '';
- form.scrollIntoView({ behavior: 'smooth', block: 'center' });
- document.getElementById('shop-f-name').focus();
+ const TYPE_OPTIONS = [
+ { v: 'frame', l: 'Рамка' },
+ { v: 'title', l: 'Титул' },
+ { v: 'background', l: 'Фон' },
+ { v: 'effect', l: 'Эффект' },
+ ];
+
+ /* Open the add/edit item modal. item = null → create, object → edit. */
+ function openItemModal(item) {
+ const isEdit = !!item;
+ const dataStr = item && item.data
+ ? (typeof item.data === 'string' ? item.data : JSON.stringify(item.data))
+ : '';
+
+ const body = document.createElement('div');
+ body.innerHTML = `
+
+
+ `;
+
+ const $ = sel => body.querySelector(sel);
+ $('#shop-f-name').value = item?.name || '';
+ $('#shop-f-type').value = item?.type || 'frame';
+ $('#shop-f-price').value = item?.price ?? 100;
+ $('#shop-f-desc').value = item?.description || '';
+ $('#shop-f-icon').value = item?.icon || '';
+ $('#shop-f-data').value = dataStr;
+ $('#shop-f-active').checked = item ? !!item.is_active : true;
+
+ let saving = false;
+ const m = LS.modal({
+ title: isEdit ? ('Редактировать товар #' + item.id) : 'Добавить товар',
+ content: body,
+ size: 'md',
+ actions: [
+ { label: 'Отмена', onClick: () => m.close() },
+ { label: 'Сохранить', primary: true, id: 'shop-save-btn', onClick: async () => {
+ if (saving) return;
+ const payload = {
+ name: $('#shop-f-name').value.trim(),
+ type: $('#shop-f-type').value,
+ price: parseInt($('#shop-f-price').value, 10) || 0,
+ description: $('#shop-f-desc').value.trim(),
+ icon: $('#shop-f-icon').value.trim(),
+ data: $('#shop-f-data').value.trim() || null,
+ is_active: $('#shop-f-active').checked ? 1 : 0,
+ };
+ if (!payload.name) { m.setError('Введите название'); return; }
+ if (payload.data) {
+ try { JSON.parse(payload.data); }
+ catch { m.setError('Поле «Данные» — некорректный JSON'); return; }
+ }
+ saving = true;
+ const btn = document.getElementById('shop-save-btn');
+ if (btn) { btn.disabled = true; btn.textContent = 'Сохранение…'; }
+ try {
+ if (isEdit) { await LS.adminShopUpdateItem(item.id, payload); LS.toast('Товар обновлён', 'success'); }
+ else { await LS.adminShopCreateItem(payload); LS.toast('Товар создан', 'success'); }
+ m.close();
+ inited = false;
+ await load();
+ inited = true;
+ } catch(e) {
+ m.setError('Ошибка: ' + e.message);
+ saving = false;
+ if (btn) { btn.disabled = false; btn.textContent = 'Сохранить'; }
+ }
+ } },
+ ],
+ });
+ setTimeout(() => $('#shop-f-name')?.focus(), 80);
}
- function shopAdminCreateItem() {
- _shopEditId = null;
- document.getElementById('shop-form-title').textContent = 'Добавить товар';
- document.getElementById('shop-f-name').value = '';
- document.getElementById('shop-f-type').value = 'frame';
- document.getElementById('shop-f-price').value = '100';
- document.getElementById('shop-f-desc').value = '';
- document.getElementById('shop-f-icon').value = '';
- document.getElementById('shop-f-data').value = '';
- document.getElementById('shop-f-active').checked = true;
- showShopForm();
- }
+ function shopAdminCreateItem() { openItemModal(null); }
function shopAdminEditItem(id) {
const it = _shopItems.find(i => i.id === id);
- if (!it) return;
- _shopEditId = id;
- document.getElementById('shop-form-title').textContent = 'Редактировать товар #' + id;
- document.getElementById('shop-f-name').value = it.name || '';
- document.getElementById('shop-f-type').value = it.type || 'frame';
- document.getElementById('shop-f-price').value = it.price ?? 100;
- document.getElementById('shop-f-desc').value = it.description || '';
- document.getElementById('shop-f-icon').value = it.icon || '';
- document.getElementById('shop-f-data').value = it.data ? (typeof it.data === 'string' ? it.data : JSON.stringify(it.data)) : '';
- document.getElementById('shop-f-active').checked = !!it.is_active;
- showShopForm();
- }
-
- function shopAdminCancelForm() {
- document.getElementById('shop-item-form').style.display = 'none';
- _shopEditId = null;
- }
-
- async function shopAdminSaveItem() {
- if (_shopSaving) return;
- _shopSaving = true;
- const data = {
- name: document.getElementById('shop-f-name').value.trim(),
- type: document.getElementById('shop-f-type').value,
- price: parseInt(document.getElementById('shop-f-price').value) || 0,
- description: document.getElementById('shop-f-desc').value.trim(),
- icon: document.getElementById('shop-f-icon').value.trim(),
- data: document.getElementById('shop-f-data').value.trim() || null,
- is_active: document.getElementById('shop-f-active').checked ? 1 : 0
- };
- if (!data.name) { LS.toast('Введите название', 'error'); _shopSaving = false; return; }
- try {
- if (_shopEditId) {
- await LS.adminShopUpdateItem(_shopEditId, data);
- LS.toast('Товар обновлён', 'success');
- } else {
- await LS.adminShopCreateItem(data);
- LS.toast('Товар создан', 'success');
- }
- shopAdminCancelForm();
- inited = false;
- await load();
- inited = true;
- } catch(e) { LS.toast('Ошибка: ' + e.message, 'error'); }
- finally { _shopSaving = false; }
+ if (it) openItemModal(it);
}
async function shopAdminDeleteItem(id) {
@@ -157,8 +202,6 @@
// Expose onclick handlers
window.shopAdminCreateItem = shopAdminCreateItem;
window.shopAdminEditItem = shopAdminEditItem;
- window.shopAdminCancelForm = shopAdminCancelForm;
- window.shopAdminSaveItem = shopAdminSaveItem;
window.shopAdminDeleteItem = shopAdminDeleteItem;
window.shopAdminToggleActive = shopAdminToggleActive;