/** * Admin Users Management Module * Handles user CRUD operations, email broadcasting, and user administration */ // User management state let allUsersData = []; // User Management Functions async function loadUsers() { const loadingEl = document.getElementById('users-loading'); const emptyEl = document.getElementById('users-empty'); const tableBody = document.getElementById('users-table-body'); if (loadingEl) loadingEl.style.display = 'block'; if (emptyEl) emptyEl.style.display = 'none'; if (tableBody) tableBody.innerHTML = ''; try { const response = await fetch('/api/users'); const data = await response.json(); if (loadingEl) loadingEl.style.display = 'none'; if (data.success && data.users) { displayUsers(data.users); } else { throw new Error(data.error || 'Failed to load users'); } } catch (error) { console.error('Error loading users:', error); if (loadingEl) loadingEl.style.display = 'none'; if (emptyEl) { emptyEl.textContent = 'Failed to load users'; emptyEl.style.display = 'block'; } window.adminCore.showStatus('Failed to load users', 'error'); } } function displayUsers(users) { const container = document.querySelector('.users-list'); if (!container) return; // Find or create the users table container, preserving the header let usersTableContainer = container.querySelector('.users-table-container'); if (!usersTableContainer) { // If container doesn't exist, create it after the header const header = container.querySelector('.users-list-header'); usersTableContainer = document.createElement('div'); usersTableContainer.className = 'users-table-container'; if (header && header.nextSibling) { container.insertBefore(usersTableContainer, header.nextSibling); } else if (header) { container.appendChild(usersTableContainer); } else { container.appendChild(usersTableContainer); } } if (!users || users.length === 0) { usersTableContainer.innerHTML = '

No users found.

'; return; } const tableHtml = `
${users.map(user => { const createdDate = user.created_at || user['Created At'] || user.createdAt; const formattedDate = createdDate ? new Date(createdDate).toLocaleDateString() : 'N/A'; const isAdmin = user.admin || user.Admin || false; const userType = user.UserType || user.userType || (isAdmin ? 'admin' : 'user'); const userId = user.Id || user.id || user.ID; // Handle expiration info let expirationInfo = ''; if (user.ExpiresAt) { const expirationDate = new Date(user.ExpiresAt); const now = new Date(); const daysUntilExpiration = Math.floor((expirationDate - now) / (1000 * 60 * 60 * 24)); if (daysUntilExpiration < 0) { expirationInfo = `Expired ${Math.abs(daysUntilExpiration)} days ago`; } else if (daysUntilExpiration <= 3) { expirationInfo = `Expires in ${daysUntilExpiration} day${daysUntilExpiration !== 1 ? 's' : ''}`; } else { expirationInfo = `Expires: ${expirationDate.toLocaleDateString()}`; } } return ` `; }).join('')}
Email Name Role Created Actions
${window.adminCore.escapeHtml(user.email || user.Email || 'N/A')} ${window.adminCore.escapeHtml(user.name || user.Name || 'N/A')} ${userType.charAt(0).toUpperCase() + userType.slice(1)} ${expirationInfo} ${formattedDate}
`; usersTableContainer.innerHTML = tableHtml; setupUserActionListeners(); } function setupUserActionListeners() { const container = document.querySelector('.users-list'); if (!container) return; // Remove existing event listeners by cloning the container const newContainer = container.cloneNode(true); container.parentNode.replaceChild(newContainer, container); // Get the updated reference const updatedContainer = document.querySelector('.users-list'); updatedContainer.addEventListener('click', function(e) { if (e.target.classList.contains('delete-user-btn')) { const userId = e.target.getAttribute('data-user-id'); const userEmail = e.target.getAttribute('data-user-email'); console.log('Delete button clicked for user:', userId); deleteUser(userId, userEmail); } else if (e.target.classList.contains('send-login-btn')) { const userId = e.target.getAttribute('data-user-id'); const userEmail = e.target.getAttribute('data-user-email'); console.log('Send login details button clicked for user:', userId); sendLoginDetailsToUser(userId, userEmail); } else if (e.target.id === 'email-all-users-btn') { console.log('Email All Users button clicked'); showEmailUsersModal(); } }); } async function deleteUser(userId, userEmail) { if (!confirm(`Are you sure you want to delete user "${userEmail}"? This action cannot be undone.`)) { return; } try { const response = await fetch(`/api/users/${userId}`, { method: 'DELETE' }); const data = await response.json(); if (data.success) { window.adminCore.showStatus(`User "${userEmail}" deleted successfully`, 'success'); loadUsers(); // Reload the users list } else { throw new Error(data.error || 'Failed to delete user'); } } catch (error) { console.error('Error deleting user:', error); window.adminCore.showStatus(`Failed to delete user: ${error.message}`, 'error'); } } async function sendLoginDetailsToUser(userId, userEmail) { if (!confirm(`Send login details to "${userEmail}"?`)) { return; } try { const response = await fetch(`/api/users/${userId}/send-login-details`, { method: 'POST', headers: { 'Content-Type': 'application/json' } }); const data = await response.json(); if (data.success) { window.adminCore.showStatus(`Login details sent to "${userEmail}" successfully`, 'success'); } else { throw new Error(data.error || 'Failed to send login details'); } } catch (error) { console.error('Error sending login details:', error); window.adminCore.showStatus(`Failed to send login details: ${error.message}`, 'error'); } } async function createUser(e) { e.preventDefault(); const emailInput = document.getElementById('user-email'); const passwordInput = document.getElementById('user-password'); const nameInput = document.getElementById('user-name'); const userTypeSelect = document.getElementById('user-type'); const expireDaysInput = document.getElementById('user-expire-days'); const adminCheckbox = document.getElementById('user-is-admin'); const email = emailInput?.value.trim(); const password = passwordInput?.value; const name = nameInput?.value.trim(); const userType = userTypeSelect?.value; const expireDays = userType === 'temp' ? parseInt(expireDaysInput?.value) : null; const admin = adminCheckbox?.checked; if (!email || !password) { window.adminCore.showStatus('Email and password are required', 'error'); return; } if (password.length < 6) { window.adminCore.showStatus('Password must be at least 6 characters long', 'error'); return; } if (userType === 'temp' && (!expireDays || expireDays < 1 || expireDays > 365)) { window.adminCore.showStatus('Expiration days must be between 1 and 365 for temporary users', 'error'); return; } try { const userData = { email, password, name: name || '', isAdmin: userType === 'admin' || admin, userType, expireDays }; const response = await fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(userData) }); const data = await response.json(); if (data.success) { window.adminCore.showStatus('User created successfully', 'success'); clearUserForm(); loadUsers(); // Reload the users list } else { throw new Error(data.error || 'Failed to create user'); } } catch (error) { console.error('Error creating user:', error); window.adminCore.showStatus(`Failed to create user: ${error.message}`, 'error'); } } function clearUserForm() { const form = document.getElementById('create-user-form'); if (form) { form.reset(); // Reset user type to default const userTypeSelect = document.getElementById('user-type'); if (userTypeSelect) { userTypeSelect.value = 'user'; } // Hide expiration group const expirationGroup = document.getElementById('expiration-group'); if (expirationGroup) { expirationGroup.style.display = 'none'; } // Re-enable admin checkbox const isAdminCheckbox = document.getElementById('user-is-admin'); if (isAdminCheckbox) { isAdminCheckbox.disabled = false; } window.adminCore.showStatus('User form cleared', 'info'); } } // Setup user-related event listeners function setupUserEventListeners() { // User form submission const userForm = document.getElementById('create-user-form'); if (userForm) { userForm.addEventListener('submit', createUser); } // Clear user form button const clearUserBtn = document.getElementById('clear-user-form'); if (clearUserBtn) { clearUserBtn.addEventListener('click', clearUserForm); } // User type change listener const userTypeSelect = document.getElementById('user-type'); if (userTypeSelect) { userTypeSelect.addEventListener('change', (e) => { const expirationGroup = document.getElementById('expiration-group'); const isAdminCheckbox = document.getElementById('user-is-admin'); if (e.target.value === 'temp') { if (expirationGroup) expirationGroup.style.display = 'block'; if (isAdminCheckbox) { isAdminCheckbox.checked = false; isAdminCheckbox.disabled = true; } } else { if (expirationGroup) expirationGroup.style.display = 'none'; if (isAdminCheckbox) isAdminCheckbox.disabled = false; if (e.target.value === 'admin') { if (isAdminCheckbox) isAdminCheckbox.checked = true; } else { if (isAdminCheckbox) isAdminCheckbox.checked = false; } } }); } } // Export user management functions window.adminUsers = { loadUsers, displayUsers, deleteUser, sendLoginDetailsToUser, createUser, clearUserForm, setupUserEventListeners, getAllUsersData: () => allUsersData, setAllUsersData: (data) => { allUsersData = data; } };