// NextSnap - Admin Panel Logic 'use strict'; const Admin = { users: [], async init() { await this.loadUsers(); this.setupEventListeners(); }, setupEventListeners() { document.getElementById('add-user-form').addEventListener('submit', (e) => { e.preventDefault(); this.createUser(); }); document.getElementById('refresh-btn').addEventListener('click', () => { this.loadUsers(); }); }, async loadUsers() { const userList = document.getElementById('user-list'); const loadingMsg = document.getElementById('loading-msg'); const errorMsg = document.getElementById('error-msg'); loadingMsg.style.display = 'block'; errorMsg.style.display = 'none'; userList.innerHTML = ''; try { const response = await fetch('/api/admin/users'); if (!response.ok) { const error = await response.json(); throw new Error(error.error || 'Failed to load users'); } const data = await response.json(); this.users = data.users || []; loadingMsg.style.display = 'none'; if (this.users.length === 0) { userList.innerHTML = 'No users found'; return; } this.users.forEach(user => { const row = this.createUserRow(user); userList.appendChild(row); }); } catch (error) { console.error('Error loading users:', error); loadingMsg.style.display = 'none'; errorMsg.textContent = error.message; errorMsg.style.display = 'block'; } }, createUserRow(user) { const row = document.createElement('tr'); row.innerHTML = ` ${this.escapeHtml(user.id)} ${this.escapeHtml(user.displayname || '-')} ${this.escapeHtml(user.email || '-')} ${user.enabled ? 'Enabled' : 'Disabled'}
${user.enabled ? `` : `` }
`; return row; }, async createUser() { const form = document.getElementById('add-user-form'); const submitBtn = document.getElementById('submit-btn'); const formError = document.getElementById('form-error'); const formSuccess = document.getElementById('form-success'); const username = document.getElementById('new-username').value.trim(); const password = document.getElementById('new-password').value; const email = document.getElementById('new-email').value.trim(); const displayName = document.getElementById('new-displayname').value.trim(); formError.style.display = 'none'; formSuccess.style.display = 'none'; if (!username || !password) { formError.textContent = 'Username and password are required'; formError.style.display = 'block'; return; } submitBtn.disabled = true; submitBtn.textContent = 'Creating...'; try { const response = await fetch('/api/admin/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: username, password: password, email: email || null, displayName: displayName || null }) }); const result = await response.json(); if (!response.ok) { throw new Error(result.error || 'Failed to create user'); } formSuccess.textContent = `User "${username}" created successfully!`; formSuccess.style.display = 'block'; form.reset(); setTimeout(() => { this.loadUsers(); }, 1000); } catch (error) { console.error('Error creating user:', error); formError.textContent = error.message; formError.style.display = 'block'; } finally { submitBtn.disabled = false; submitBtn.textContent = 'Create User'; } }, async enableUser(username) { if (!confirm(`Enable user "${username}"?`)) return; try { const response = await fetch(`/api/admin/users/${username}/enable`, { method: 'PUT' }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || 'Failed to enable user'); } this.showToast(`User "${username}" enabled`, 'success'); this.loadUsers(); } catch (error) { console.error('Error enabling user:', error); this.showToast(error.message, 'error'); } }, async disableUser(username) { if (!confirm(`Disable user "${username}"?`)) return; try { const response = await fetch(`/api/admin/users/${username}/disable`, { method: 'PUT' }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || 'Failed to disable user'); } this.showToast(`User "${username}" disabled`, 'success'); this.loadUsers(); } catch (error) { console.error('Error disabling user:', error); this.showToast(error.message, 'error'); } }, confirmDeleteUser(username) { const modal = document.getElementById('delete-modal'); const confirmBtn = document.getElementById('confirm-delete'); document.getElementById('delete-username').textContent = username; modal.style.display = 'flex'; confirmBtn.onclick = () => { this.deleteUser(username); this.hideDeleteModal(); }; }, hideDeleteModal() { document.getElementById('delete-modal').style.display = 'none'; }, async deleteUser(username) { try { const response = await fetch(`/api/admin/users/${username}`, { method: 'DELETE' }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || 'Failed to delete user'); } this.showToast(`User "${username}" deleted`, 'success'); this.loadUsers(); } catch (error) { console.error('Error deleting user:', error); this.showToast(error.message, 'error'); } }, showToast(message, type) { const toast = document.getElementById('toast'); toast.textContent = message; toast.className = `toast ${type}`; toast.style.display = 'block'; setTimeout(() => { toast.style.display = 'none'; }, 3000); }, escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } }; window.Admin = Admin;