// Authentication Handler class Auth { constructor() { this.user = null; this.isAuthenticated = false; this.checkAuth(); } async checkAuth() { try { const response = await api.getCurrentUser(); if (response.success) { this.user = response.user; this.isAuthenticated = true; return true; } } catch (error) { this.logout(); } return false; } async login(email, password) { try { const response = await api.login(email, password); if (response.success) { this.user = response.user; this.isAuthenticated = true; return { success: true, user: this.user }; } return { success: false, error: response.message }; } catch (error) { return { success: false, error: error.message }; } } async register(name, email, password) { try { const response = await api.register(name, email, password); if (response.success) { return { success: true, message: 'Регистрация успешна. Теперь вы можете войти.' }; } return { success: false, error: response.message }; } catch (error) { return { success: false, error: error.message }; } } async logout() { try { await api.logout(); } catch (error) { console.error('Logout error:', error); } this.user = null; this.isAuthenticated = false; window.location.hash = '#login'; } hasRole(role) { return this.user && this.user.role === role; } hasPermission(permission) { if (!this.user) return false; return this.user.permissions && this.user.permissions.includes(permission); } getUser() { return this.user; } isAdmin() { return this.user && (this.user.role === 'superadmin' || this.user.role === 'admin'); } isSuperAdmin() { return this.user && this.user.role === 'superadmin'; } } // Global auth instance const auth = new Auth(); // Login/Register form handler document.addEventListener('DOMContentLoaded', () => { // Tab switching const authTabBtns = document.querySelectorAll('.auth-tab-btn'); const authForms = document.querySelectorAll('.auth-form'); authTabBtns.forEach(btn => { btn.addEventListener('click', () => { const tab = btn.dataset.tab; // Update active tab authTabBtns.forEach(b => b.classList.remove('active')); btn.classList.add('active'); // Show/hide forms authForms.forEach(form => form.classList.add('hidden')); if (tab === 'login') { document.getElementById('loginForm').classList.remove('hidden'); } else { document.getElementById('registerForm').classList.remove('hidden'); } }); }); // Login form const loginForm = document.getElementById('loginForm'); if (loginForm) { loginForm.addEventListener('submit', async (e) => { e.preventDefault(); const email = document.getElementById('loginEmail').value; const password = document.getElementById('loginPassword').value; const loginText = document.querySelector('.login-text'); const loginLoader = document.querySelector('.login-loader'); loginText.style.display = 'none'; loginLoader.classList.remove('hidden'); const result = await auth.login(email, password); if (result.success) { // Redirect to dashboard setTimeout(() => { window.location.hash = '#dashboard'; }, 500); } else { showAuthError(result.error); loginText.style.display = 'block'; loginLoader.classList.add('hidden'); } }); } // Register form const registerForm = document.getElementById('registerForm'); if (registerForm) { registerForm.addEventListener('submit', async (e) => { e.preventDefault(); const name = document.getElementById('registerName').value; const email = document.getElementById('registerEmail').value; const password = document.getElementById('registerPassword').value; const confirmPassword = document.getElementById('registerPasswordConfirm').value; if (password !== confirmPassword) { showAuthError('Пароли не совпадают'); return; } const registerText = document.querySelector('.register-text'); const registerLoader = document.querySelector('.register-loader'); registerText.style.display = 'none'; registerLoader.classList.remove('hidden'); const result = await auth.register(name, email, password); if (result.success) { showAuthError(result.message, 'success'); // Clear form and switch to login registerForm.reset(); document.querySelector('[data-tab="login"]').click(); } else { showAuthError(result.error); } registerText.style.display = 'block'; registerLoader.classList.add('hidden'); }); } }); function showAuthError(message, type = 'error') { const errorDiv = document.getElementById('authError'); const errorText = document.getElementById('authErrorText'); if (type === 'success') { errorDiv.classList.remove('bg-red-50', 'border-red-200', 'text-red-600', 'dark:bg-red-900/20', 'dark:border-red-800', 'dark:text-red-400'); errorDiv.classList.add('bg-green-50', 'border-green-200', 'text-green-600', 'dark:bg-green-900/20', 'dark:border-green-800', 'dark:text-green-400'); const icon = errorDiv.querySelector('i'); if (icon) { icon.setAttribute('data-lucide', 'check-circle'); } } else { errorDiv.classList.remove('bg-green-50', 'border-green-200', 'text-green-600', 'dark:bg-green-900/20', 'dark:border-green-800', 'dark:text-green-400'); errorDiv.classList.add('bg-red-50', 'border-red-200', 'text-red-600', 'dark:bg-red-900/20', 'dark:border-red-800', 'dark:text-red-400'); const icon = errorDiv.querySelector('i'); if (icon) { icon.setAttribute('data-lucide', 'alert-circle'); } } errorText.textContent = message; errorDiv.classList.remove('hidden'); // Auto-hide success messages if (type === 'success') { setTimeout(() => { errorDiv.classList.add('hidden'); }, 3000); } // Update Lucide icons if (typeof lucide !== 'undefined') { lucide.createIcons(); } }