// Router - Single Page Application routing class Router { constructor() { this.routes = { 'login': { module: 'authModule', handler: this.handleLogin.bind(this) }, 'register': { module: 'authModule', handler: this.handleLogin.bind(this) }, 'dashboard': { module: 'dashboardModule', requireAuth: true, handler: this.handleDashboard.bind(this) }, 'databases': { module: 'dashboardModule', requireAuth: true, handler: this.handleDatabases.bind(this) }, 'tables': { module: 'dashboardModule', requireAuth: true, handler: this.handleTables.bind(this) }, 'queries': { module: 'dashboardModule', requireAuth: true, handler: this.handleQueries.bind(this) }, 'admin-users': { module: 'adminModule', requireAuth: true, requireAdmin: true, handler: this.handleAdminUsers.bind(this) }, 'admin-roles': { module: 'adminModule', requireAuth: true, requireAdmin: true, handler: this.handleAdminRoles.bind(this) }, 'admin-settings': { module: 'adminModule', requireAuth: true, requireAdmin: true, handler: this.handleAdminSettings.bind(this) }, 'admin-logs': { module: 'adminModule', requireAuth: true, requireAdmin: true, handler: this.handleAdminLogs.bind(this) }, 'admin-database': { module: 'adminModule', requireAuth: true, requireAdmin: true, handler: this.handleAdminDatabase.bind(this) }, 'admin-backups': { module: 'adminModule', requireAuth: true, requireAdmin: true, handler: this.handleAdminBackups.bind(this) }, }; this.currentRoute = null; this.modules = {}; this.init(); } async init() { // Load modules await this.loadModules(); // Setup hash change listener window.addEventListener('hashchange', () => this.navigate()); // Initial navigation this.navigate(); } async loadModules() { const modules = ['auth', 'dashboard', 'admin']; for (const module of modules) { try { const response = await fetch(`/modules/${module}/${module === 'auth' ? 'login' : module === 'admin' ? 'admin-panel' : 'dashboard'}.html`); if (response.ok) { const html = await response.text(); const container = document.createElement('div'); container.innerHTML = html; document.getElementById('app').appendChild(container); } } catch (error) { console.error(`Failed to load ${module} module:`, error); } } // Update Lucide icons after loading modules if (typeof lucide !== 'undefined') { lucide.createIcons(); } } navigate() { const hash = window.location.hash.slice(1) || 'login'; const route = this.routes[hash]; if (!route) { window.location.hash = '#login'; return; } // Check authentication if (route.requireAuth && !auth.isAuthenticated) { window.location.hash = '#login'; return; } // Check admin permission if (route.requireAdmin && !auth.isAdmin()) { window.location.hash = '#dashboard'; return; } // Hide all modules document.querySelectorAll('[id$="Module"]').forEach(mod => { mod.classList.add('hidden'); }); // Show target module const module = document.getElementById(route.module); if (module) { module.classList.remove('hidden'); } // Close sidebars on mobile when navigating const sidebars = document.querySelectorAll('[id$="Sidebar"]'); sidebars.forEach(sidebar => { sidebar.classList.add('hidden'); }); // Call route handler if (route.handler) { route.handler(); } // Setup navigation event listeners for current route this.setupNavigation(); // Update Lucide icons if (typeof lucide !== 'undefined') { lucide.createIcons(); } this.currentRoute = hash; } setupNavigation() { // Sidebar toggle const toggleBtn = document.getElementById('toggleSidebar'); const sidebar = document.getElementById('sidebar'); if (toggleBtn && sidebar) { toggleBtn.onclick = () => sidebar.classList.toggle('-translate-x-full'); } // Admin sidebar toggle const toggleAdminBtn = document.getElementById('toggleAdminSidebar'); const adminSidebar = document.getElementById('adminSidebar'); if (toggleAdminBtn && adminSidebar) { toggleAdminBtn.onclick = () => adminSidebar.classList.toggle('-translate-x-full'); } // Logout buttons const logoutBtn = document.getElementById('logoutBtn'); if (logoutBtn) { logoutBtn.onclick = () => { if (confirm('Вы уверены, что хотите выйти?')) { auth.logout(); } }; } const adminLogoutBtn = document.getElementById('adminLogoutBtn'); if (adminLogoutBtn) { adminLogoutBtn.onclick = () => { if (confirm('Вы уверены, что хотите выйти?')) { auth.logout(); } }; } // Update user info if (auth.isAuthenticated && auth.user) { const userName = document.getElementById('userName'); const userRole = document.getElementById('userRole'); const avatarCircle = document.getElementById('avatarCircle'); if (userName) userName.textContent = auth.user.name || 'User'; if (userRole) userRole.textContent = this.getRoleName(auth.user.role); if (avatarCircle) avatarCircle.textContent = (auth.user.name || 'A').charAt(0).toUpperCase(); } // Navigation items const navItems = document.querySelectorAll('.nav-item'); navItems.forEach(item => { item.classList.remove('active'); if (item.getAttribute('href') === `#${this.currentRoute}`) { item.classList.add('active'); } item.addEventListener('click', () => { navItems.forEach(n => n.classList.remove('active')); item.classList.add('active'); // Close sidebar on mobile const sidebar = document.getElementById('sidebar') || document.getElementById('adminSidebar'); if (sidebar) { sidebar.classList.add('-translate-x-full'); } }); }); } getRoleName(role) { const names = { 'superadmin': 'Суперадминистратор', 'admin': 'Администратор', 'moderator': 'Модератор', 'viewer': 'Только просмотр' }; return names[role] || role; } // Route handlers handleLogin() { } handleDashboard() { } handleDatabases() { } handleTables() { } handleQueries() { } handleAdminUsers() { } handleAdminRoles() { } handleAdminSettings() { } handleAdminLogs() { } handleAdminDatabase() { } handleAdminBackups() { } } // Initialize router const router = new Router();