document.addEventListener('DOMContentLoaded', function() { // Initialize user management initUserManagement(); // Event listeners document.getElementById('userSearch').addEventListener('input', filterUsers); document.getElementById('roleFilter').addEventListener('change', filterUsers); document.getElementById('statusFilter').addEventListener('change', filterUsers); document.getElementById('addUserBtn').addEventListener('click', showAddUserModal); document.getElementById('cancelUser').addEventListener('click', hideUserModal); document.getElementById('saveUser').addEventListener('click', saveUser); document.getElementById('userActivityFilter').addEventListener('change', loadActivityLog); document.getElementById('savePassword').addEventListener('click', changePassword); document.getElementById('cancelPassword').addEventListener('click', hidePasswordModal); // Close modals when clicking on X document.querySelectorAll('.close-modal').forEach(button => { button.addEventListener('click', function() { this.closest('.modal').classList.remove('show'); }); }); }); // Global variables let users = []; let currentPage = 1; let totalPages = 1; let itemsPerPage = 10; // Initialize user management async function initUserManagement() { try { // Check if current user is admin const userJson = localStorage.getItem('posUser'); if (userJson) { const currentUser = JSON.parse(userJson); if (currentUser.role !== 'admin') { // Redirect non-admin users window.location.href = `${basePath}/admin/index.html`; return; } } // Load users await loadUsers(); // Load initial activity log loadActivityLog(); } catch (error) { console.error('Failed to initialize user management:', error); showNotification('Error loading user data', 'error'); } } // Load users from API async function loadUsers() { try { const response = await apiRequest('users/all'); if (response.status === 'success') { users = response.data; renderUsers(users); populateUserActivityFilter(); } else { showNotification(response.message || 'Failed to load users', 'error'); } } catch (error) { console.error('Error loading users:', error); showNotification('Error loading users', 'error'); } } // Render users table function renderUsers(usersToRender) { const tableBody = document.querySelector('#usersTable tbody'); tableBody.innerHTML = ''; if (usersToRender.length === 0) { const row = document.createElement('tr'); row.innerHTML = 'No users found'; tableBody.appendChild(row); return; } usersToRender.forEach(user => { const row = document.createElement('tr'); // Format last login date const lastLogin = user.last_login ? new Date(user.last_login).toLocaleString() : 'Never'; row.innerHTML = ` ${user.username} ${user.full_name} ${user.email} ${user.role} ${user.status} ${lastLogin} `; tableBody.appendChild(row); }); // Add event listeners for action buttons document.querySelectorAll('.edit-user').forEach(button => { button.addEventListener('click', function() { const userId = this.dataset.id; editUser(userId); }); }); document.querySelectorAll('.change-password').forEach(button => { button.addEventListener('click', function() { const userId = this.dataset.id; showPasswordModal(userId); }); }); document.querySelectorAll('.delete-user').forEach(button => { button.addEventListener('click', function() { const userId = this.dataset.id; deleteUser(userId); }); }); } // Populate user filter for activity log function populateUserActivityFilter() { const select = document.getElementById('userActivityFilter'); // Clear existing options (except the first one) while (select.options.length > 1) { select.remove(1); } // Add users to the filter users.forEach(user => { const option = document.createElement('option'); option.value = user.id; option.textContent = `${user.username} (${user.full_name})`; select.appendChild(option); }); } // Filter users based on search and filters function filterUsers() { const searchTerm = document.getElementById('userSearch').value.toLowerCase(); const roleFilter = document.getElementById('roleFilter').value; const statusFilter = document.getElementById('statusFilter').value; let filtered = [...users]; // Apply search filter if (searchTerm) { filtered = filtered.filter(user => { return user.username.toLowerCase().includes(searchTerm) || user.full_name.toLowerCase().includes(searchTerm) || user.email.toLowerCase().includes(searchTerm); }); } // Apply role filter if (roleFilter) { filtered = filtered.filter(user => user.role === roleFilter); } // Apply status filter if (statusFilter) { filtered = filtered.filter(user => user.status === statusFilter); } renderUsers(filtered); } // Show add user modal function showAddUserModal() { // Reset form document.getElementById('userForm').reset(); document.getElementById('userId').value = ''; document.getElementById('userModalTitle').textContent = 'Add User'; // Show password fields and make them required const passwordFields = document.querySelectorAll('.password-fields input'); passwordFields.forEach(field => { field.required = true; field.disabled = false; }); document.querySelector('.password-fields').style.display = 'flex'; document.querySelector('.password-fields .form-hint').style.display = 'none'; // Enable username field document.getElementById('username').disabled = false; // Set default status to active document.getElementById('status').value = 'active'; // Show modal document.getElementById('userModal').classList.add('show'); } // Show edit user modal async function editUser(userId) { try { const response = await apiRequest(`users/user?id=${userId}`); if (response.status === 'success') { const user = response.data; // Fill form fields document.getElementById('userId').value = user.id; document.getElementById('username').value = user.username; document.getElementById('username').disabled = true; // Username cannot be changed document.getElementById('email').value = user.email; document.getElementById('fullName').value = user.full_name; document.getElementById('role').value = user.role; document.getElementById('status').value = user.status; // Hide password fields document.querySelector('.password-fields').style.display = 'none'; const passwordFields = document.querySelectorAll('.password-fields input'); passwordFields.forEach(field => { field.required = false; field.disabled = true; }); // Update modal title document.getElementById('userModalTitle').textContent = 'Edit User'; // Show modal document.getElementById('userModal').classList.add('show'); } else { showNotification(response.message || 'Failed to load user details', 'error'); } } catch (error) { console.error('Error loading user details:', error); showNotification('Error loading user details', 'error'); } } // Hide user modal function hideUserModal() { document.getElementById('userModal').classList.remove('show'); } // Save user (create or update) async function saveUser() { try { const userId = document.getElementById('userId').value; const isNewUser = !userId; // Validate form const form = document.getElementById('userForm'); if (!form.checkValidity()) { form.reportValidity(); return; } // Validate passwords match for new users if (isNewUser) { const password = document.getElementById('password').value; const confirmPassword = document.getElementById('confirmPassword').value; if (password !== confirmPassword) { showNotification('Passwords do not match', 'error'); return; } } // Gather form data const userData = { username: document.getElementById('username').value, email: document.getElementById('email').value, full_name: document.getElementById('fullName').value, role: document.getElementById('role').value, status: document.getElementById('status').value }; // Add password for new users if (isNewUser) { userData.password = document.getElementById('password').value; } let response; if (isNewUser) { // Create new user response = await apiRequest('users', 'POST', userData); } else { // Update existing user response = await apiRequest(`users/user?id=${userId}`, 'PUT', userData); } if (response.status === 'success') { showNotification(isNewUser ? 'User created successfully' : 'User updated successfully', 'success'); hideUserModal(); await loadUsers(); // Reload users } else { showNotification(response.message || 'Failed to save user', 'error'); } } catch (error) { console.error('Error saving user:', error); showNotification('Error saving user', 'error'); } } // Delete user async function deleteUser(userId) { // Don't allow deletion of self const userJson = localStorage.getItem('posUser'); if (userJson) { const currentUser = JSON.parse(userJson); if (currentUser.id == userId) { showNotification('You cannot delete your own account', 'error'); return; } } if (confirm('Are you sure you want to delete this user? This action cannot be undone.')) { try { const response = await apiRequest(`users/user?id=${userId}`, 'DELETE'); if (response.status === 'success') { showNotification('User deleted successfully', 'success'); await loadUsers(); // Reload users } else { showNotification(response.message || 'Failed to delete user', 'error'); } } catch (error) { console.error('Error deleting user:', error); showNotification('Error deleting user', 'error'); } } } // Show password change modal function showPasswordModal(userId) { document.getElementById('passwordForm').reset(); document.getElementById('passwordUserId').value = userId; document.getElementById('passwordModal').classList.add('show'); } // Hide password change modal function hidePasswordModal() { document.getElementById('passwordModal').classList.remove('show'); } // Change user password async function changePassword() { try { const userId = document.getElementById('passwordUserId').value; const newPassword = document.getElementById('newPassword').value; const confirmNewPassword = document.getElementById('confirmNewPassword').value; // Validate form const form = document.getElementById('passwordForm'); if (!form.checkValidity()) { form.reportValidity(); return; } // Validate passwords match if (newPassword !== confirmNewPassword) { showNotification('Passwords do not match', 'error'); return; } const response = await apiRequest('users/change-password', 'POST', { user_id: userId, new_password: newPassword }); if (response.status === 'success') { showNotification('Password changed successfully', 'success'); hidePasswordModal(); } else { showNotification(response.message || 'Failed to change password', 'error'); } } catch (error) { console.error('Error changing password:', error); showNotification('Error changing password', 'error'); } } // Load activity log async function loadActivityLog() { try { const userId = document.getElementById('userActivityFilter').value; const params = new URLSearchParams({ page: currentPage, limit: itemsPerPage }); if (userId) { params.append('user_id', userId); } const response = await apiRequest(`users/activity-log?${params.toString()}`); if (response.status === 'success') { renderActivityLog(response.data.logs); totalPages = response.data.pagination.pages; renderPagination(response.data.pagination); } else { showNotification(response.message || 'Failed to load activity log', 'error'); } } catch (error) { console.error('Error loading activity log:', error); showNotification('Error loading activity log', 'error'); } } // Render activity log table function renderActivityLog(logs) { const tableBody = document.querySelector('#activityLogTable tbody'); tableBody.innerHTML = ''; if (logs.length === 0) { const row = document.createElement('tr'); row.innerHTML = 'No activity logs found'; tableBody.appendChild(row); return; } logs.forEach(log => { const row = document.createElement('tr'); // Format date const date = new Date(log.created_at).toLocaleString(); row.innerHTML = ` ${log.username} ${log.action} ${log.description || '-'} ${log.ip_address} ${date} `; tableBody.appendChild(row); }); } // Render pagination function renderPagination(pagination) { const paginationContainer = document.getElementById('activityPagination'); paginationContainer.innerHTML = ''; if (pagination.pages <= 1) { return; } // Create pagination elements const prevBtn = document.createElement('button'); prevBtn.classList.add('pagination-btn'); prevBtn.disabled = pagination.page === 1; prevBtn.innerHTML = ''; prevBtn.addEventListener('click', () => changePage(pagination.page - 1)); const nextBtn = document.createElement('button'); nextBtn.classList.add('pagination-btn'); nextBtn.disabled = pagination.page === pagination.pages; nextBtn.innerHTML = ''; nextBtn.addEventListener('click', () => changePage(pagination.page + 1)); const pageInfo = document.createElement('span'); pageInfo.classList.add('pagination-info'); pageInfo.textContent = `Page ${pagination.page} of ${pagination.pages}`; paginationContainer.appendChild(prevBtn); paginationContainer.appendChild(pageInfo); paginationContainer.appendChild(nextBtn); } // Change activity log page function changePage(page) { currentPage = page; loadActivityLog(); }