// 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;