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();
}