// Mobile menu
function toggleMobileMenu() {
const overlay = document.getElementById('mobile-menu-overlay');
const panel = document.getElementById('mobile-menu-panel');
if (!overlay || !panel) return;
const isOpen = panel.style.display === 'block';
if (isOpen) {
overlay.style.display = 'none';
panel.style.display = 'none';
} else {
overlay.style.display = 'block';
panel.style.display = 'block';
document.querySelectorAll('.mm-item').forEach(function(el) {
el.classList.toggle('active', el.dataset.page === window._currentPage);
});
const mmUsers = document.getElementById('mm-users');
if (mmUsers && window._currentUser) {
mmUsers.style.display = window._currentUser.role === 'admin' ? '' : 'none';
}
}
}
function closeMobileMenu() {
const overlay = document.getElementById('mobile-menu-overlay');
const panel = document.getElementById('mobile-menu-panel');
if (overlay) overlay.style.display = 'none';
if (panel) panel.style.display = 'none';
}
// Handle mm-item clicks
document.addEventListener('click', function(e) {
const item = e.target.closest('.mm-item');
if (item && item.dataset.page) {
closeMobileMenu();
setPage(item.dataset.page);
}
});
// Sidebar toggle for mobile
function toggleSidebar() {
const sidebar = document.querySelector('.sidebar');
if (!sidebar) return;
const isOpen = sidebar.style.transform === 'translateX(0px)' || sidebar.classList.contains('open');
if (isOpen) {
sidebar.style.transform = '';
sidebar.classList.remove('open');
document.getElementById('sidebar-overlay') && document.getElementById('sidebar-overlay').remove();
} else {
sidebar.style.transform = 'translateX(0)';
sidebar.classList.add('open');
const ov = document.createElement('div');
ov.id = 'sidebar-overlay';
ov.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.4);z-index:49';
ov.onclick = function(){ toggleSidebar(); };
document.body.appendChild(ov);
}
}
Воронка продаж
Конверсия сегодня
Деньги по каналам
Яндекс Метрика
Топ товаров за неделю
По прибыли · с остатками
';
document.body.appendChild(modal);
const roleEl=document.getElementById('um-role');
if(roleEl) roleEl.addEventListener('change',function(){const ps=document.getElementById('um-pages-section');if(ps)ps.style.display=this.value==='admin'?'none':'';});
if(user&&user.role==='admin'){const ps=document.getElementById('um-pages-section');if(ps)ps.style.display='none';}
}
async function saveUser(id){
const name=document.getElementById('um-name').value.trim();
const username=document.getElementById('um-username').value.trim();
const password=document.getElementById('um-password').value;
const role=document.getElementById('um-role').value;
const activeEl=document.getElementById('um-active');
const active=activeEl?activeEl.checked:true;
const pages=Array.from(document.querySelectorAll('#um-pages-section input[type=checkbox]:checked')).map(function(c){return c.value;});
const err=document.getElementById('um-err');
if(!name){err.textContent='Введите имя';err.style.display='block';return;}
if(!id&&!password){err.textContent='Введите пароль';err.style.display='block';return;}
err.style.display='none';
try{
const token=localStorage.getItem('auth_token');
const body={name:name,role:role,active:active,pages:pages};
if(password) body.password=password;
if(!id) body.username=username;
const r=await fetch(id?'/api/auth/users/'+id:'/api/auth/users',{method:id?'PUT':'POST',headers:{'Content-Type':'application/json','x-auth-token':token},body:JSON.stringify(body)});
const data=await r.json();
if(!r.ok){err.textContent=data.error;err.style.display='block';return;}
const m=document.getElementById('user-modal');if(m)m.remove();
showToast('Пользователь сохранён','success');
loadUsersList();
}catch(e){err.textContent='Ошибка';err.style.display='block';}
}
async function deleteUser(id){
if(!confirm('Удалить пользователя?')) return;
const r=await fetch('/api/auth/users/'+id,{method:'DELETE',headers:{'x-auth-token':localStorage.getItem('auth_token')}});
if(r.ok){const m=document.getElementById('user-modal');if(m)m.remove();showToast('Пользователь удалён','info');loadUsersList();}
}