'use strict';
/* admin → shop section: items + purchases + award coins */
(function () {
'use strict';
let inited = false;
let _shopItems = [];
let _shopEditId = null;
let _shopSaving = false;
let _shopSearchTimer = null;
let _coinsAwarding = false;
async function load() {
try {
const [stats, items] = await Promise.all([
LS.adminShopStats(),
LS.adminShopGetItems()
]);
const topName = stats.topItems?.[0]?.name || '—';
document.getElementById('shop-stats-grid').innerHTML = `
${stats.activeItems}/${stats.totalItems}
Товаров
${stats.totalPurchases}
Покупок
${stats.totalCoinsInCirculation}
Монет в обороте
${esc(topName)}
Топ товар
`;
_shopItems = items;
renderShopItems();
if (window.lucide) lucide.createIcons();
} catch(e) {
document.getElementById('shop-stats-grid').innerHTML = `Ошибка: ${esc(e.message)}
`;
}
}
function renderShopItems() {
const body = document.getElementById('shop-items-body');
if (!_shopItems.length) { body.innerHTML = '| Нет товаров |
'; return; }
const typeLabels = { frame:'Рамка', title:'Титул', theme:'Тема', effect:'Эффект' };
body.innerHTML = _shopItems.map(it => `
| ${it.id} |
${esc(it.name)} |
${typeLabels[it.type] || esc(it.type)} |
${it.price} |
${it.sold_count || 0} |
|
|
`).join('');
if (window.lucide) lucide.createIcons();
}
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;
document.getElementById('shop-item-form').style.display = '';
}
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;
document.getElementById('shop-item-form').style.display = '';
}
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; }
}
async function shopAdminDeleteItem(id) {
if (!await LS.confirm('Все покупки этого товара будут удалены.', { title: 'Удалить товар?', confirmText: 'Удалить', danger: true })) return;
try {
await LS.adminShopDeleteItem(id);
LS.toast('Товар удалён', 'success');
inited = false;
await load();
inited = true;
} catch(e) { LS.toast('Ошибка: ' + e.message, 'error'); }
}
async function shopAdminToggleActive(id, active) {
try {
await LS.adminShopUpdateItem(id, { is_active: active ? 1 : 0 });
LS.toast(active ? 'Товар активирован' : 'Товар деактивирован', 'success');
} catch(e) { LS.toast('Ошибка: ' + e.message, 'error'); }
}
async function shopSearchUser(q) {
clearTimeout(_shopSearchTimer);
const box = document.getElementById('shop-award-results');
if (q.length < 2) { box.classList.remove('open'); return; }
_shopSearchTimer = setTimeout(async () => {
try {
const r = await LS.adminGetUsers({ q, limit: 8 });
const label = u => u.name || u.email;
box.innerHTML = (r.users || []).map(u => `
${esc(label(u))}${esc(u.role)}
`).join('') || 'Не найдено
';
box.classList.add('open');
} catch(e) { box.classList.remove('open'); }
}, 300);
}
function shopPickUser(el) {
document.getElementById('shop-award-uid').value = el.dataset.uid;
document.getElementById('shop-award-user').value = el.dataset.name || '';
document.getElementById('shop-award-results').classList.remove('open');
}
async function shopAdminAwardCoins() {
if (_coinsAwarding) return;
const userId = parseInt(document.getElementById('shop-award-uid').value);
const amount = parseInt(document.getElementById('shop-award-amount').value);
const reason = document.getElementById('shop-award-reason').value.trim();
if (!userId) { LS.toast('Выберите пользователя', 'error'); return; }
if (!amount || amount <= 0) { LS.toast('Введите количество монет', 'error'); return; }
_coinsAwarding = true;
try {
const r = await LS.adminShopAwardCoins({ userId, amount, reason });
LS.toast(`Начислено ${amount} монет. Баланс: ${r.coins}`, 'success');
document.getElementById('shop-award-uid').value = '';
document.getElementById('shop-award-user').value = '';
document.getElementById('shop-award-reason').value = '';
} catch(e) { LS.toast('Ошибка: ' + e.message, 'error'); }
finally { _coinsAwarding = false; }
}
// Expose onclick handlers
window.shopAdminCreateItem = shopAdminCreateItem;
window.shopAdminEditItem = shopAdminEditItem;
window.shopAdminCancelForm = shopAdminCancelForm;
window.shopAdminSaveItem = shopAdminSaveItem;
window.shopAdminDeleteItem = shopAdminDeleteItem;
window.shopAdminToggleActive = shopAdminToggleActive;
window.shopSearchUser = shopSearchUser;
window.shopPickUser = shopPickUser;
window.shopAdminAwardCoins = shopAdminAwardCoins;
window.AdminSections = window.AdminSections || {};
window.AdminSections.shop = {
init: async () => { if (inited) return; inited = true; await load(); },
reload: load,
};
})();