Fix icon hover colors, text alignment, and UI improvements
This commit is contained in:
+97
-79
@@ -112,6 +112,12 @@
|
||||
<span>Bookings</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/admin/availability.html" class="nav-link">
|
||||
<i class="fas fa-clock"></i>
|
||||
<span>Availability</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -154,7 +160,7 @@
|
||||
</div>
|
||||
|
||||
<div class="header-right">
|
||||
<button class="btn btn-primary" onclick="openAddUserModal()">
|
||||
<button class="btn btn-primary" id="add-user-btn">
|
||||
<i class="fas fa-user-plus"></i> Add User
|
||||
</button>
|
||||
|
||||
@@ -223,8 +229,8 @@
|
||||
<div class="roles-grid">
|
||||
<div class="role-card">
|
||||
<div class="role-header">
|
||||
<span class="role-badge super-admin">Super Admin</span>
|
||||
<span class="role-count">1 user</span>
|
||||
<span class="role-badge admin">Administrator</span>
|
||||
<span class="role-count" id="count-admin">— users</span>
|
||||
</div>
|
||||
<ul class="permissions-list">
|
||||
<li><i class="fas fa-check"></i> Full system access</li>
|
||||
@@ -238,7 +244,7 @@
|
||||
<div class="role-card">
|
||||
<div class="role-header">
|
||||
<span class="role-badge editor">Editor</span>
|
||||
<span class="role-count">1 user</span>
|
||||
<span class="role-count" id="count-editor">— users</span>
|
||||
</div>
|
||||
<ul class="permissions-list">
|
||||
<li><i class="fas fa-check"></i> Create/edit content</li>
|
||||
@@ -248,20 +254,6 @@
|
||||
<li><i class="fas fa-times"></i> Site settings</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="role-card">
|
||||
<div class="role-header">
|
||||
<span class="role-badge contributor">Contributor</span>
|
||||
<span class="role-count">1 user</span>
|
||||
</div>
|
||||
<ul class="permissions-list">
|
||||
<li><i class="fas fa-check"></i> Create content</li>
|
||||
<li><i class="fas fa-times"></i> Publish content</li>
|
||||
<li><i class="fas fa-check"></i> Upload media</li>
|
||||
<li><i class="fas fa-times"></i> Delete content</li>
|
||||
<li><i class="fas fa-times"></i> Site settings</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -270,48 +262,12 @@
|
||||
<div class="card" style="margin-top: 2rem;">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-history"></i> Recent Activity</h3>
|
||||
<a href="#" class="card-action">View All</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="activity-timeline">
|
||||
<div class="activity-item">
|
||||
<div class="activity-icon login">
|
||||
<i class="fas fa-sign-in-alt"></i>
|
||||
</div>
|
||||
<div class="activity-content">
|
||||
<p><strong>Super Admin</strong> logged in</p>
|
||||
<span class="activity-time">10 minutes ago</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="activity-item">
|
||||
<div class="activity-icon edit">
|
||||
<i class="fas fa-edit"></i>
|
||||
</div>
|
||||
<div class="activity-content">
|
||||
<p><strong>Sarah Johnson</strong> edited <em>"New IT Security Features"</em></p>
|
||||
<span class="activity-time">2 hours ago</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="activity-item">
|
||||
<div class="activity-icon create">
|
||||
<i class="fas fa-plus"></i>
|
||||
</div>
|
||||
<div class="activity-content">
|
||||
<p><strong>Sarah Johnson</strong> created new news article</p>
|
||||
<span class="activity-time">Yesterday</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="activity-item">
|
||||
<div class="activity-icon settings">
|
||||
<i class="fas fa-cog"></i>
|
||||
</div>
|
||||
<div class="activity-content">
|
||||
<p><strong>Super Admin</strong> updated site settings</p>
|
||||
<span class="activity-time">2 days ago</span>
|
||||
</div>
|
||||
<div class="activity-timeline" id="activity-timeline">
|
||||
<div class="empty-state" style="padding: 2rem; text-align: center;">
|
||||
<i class="fas fa-history" style="font-size: 2rem; opacity: 0.3; margin-bottom: 0.5rem; display:block;"></i>
|
||||
<p>Activity is recorded in the server error log under <code>[MSPE_AUDIT]</code> entries.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -326,7 +282,7 @@
|
||||
<div class="modal-container">
|
||||
<div class="modal-header">
|
||||
<h2 id="modal-title">Add Admin User</h2>
|
||||
<button class="modal-close" onclick="closeModal()">×</button>
|
||||
<button class="modal-close" id="user-modal-close">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="user-form">
|
||||
@@ -361,9 +317,8 @@
|
||||
<div class="form-group">
|
||||
<label>Role *</label>
|
||||
<select class="form-select" name="role" required>
|
||||
<option value="contributor">Contributor</option>
|
||||
<option value="editor">Editor</option>
|
||||
<option value="super-admin">Super Admin</option>
|
||||
<option value="admin">Administrator</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@@ -384,8 +339,8 @@
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-outline" onclick="closeModal()">Cancel</button>
|
||||
<button class="btn btn-primary" onclick="saveUser()">
|
||||
<button class="btn btn-outline" id="user-cancel-btn">Cancel</button>
|
||||
<button class="btn btn-primary" id="user-save-btn">
|
||||
<i class="fas fa-save"></i> Save User
|
||||
</button>
|
||||
</div>
|
||||
@@ -398,7 +353,7 @@
|
||||
<div class="modal-container modal-sm">
|
||||
<div class="modal-header">
|
||||
<h2>Change Password</h2>
|
||||
<button class="modal-close" onclick="closePasswordModal()">×</button>
|
||||
<button class="modal-close" id="password-modal-close">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="password-form">
|
||||
@@ -419,8 +374,8 @@
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-outline" onclick="closePasswordModal()">Cancel</button>
|
||||
<button class="btn btn-primary" onclick="updatePassword()">
|
||||
<button class="btn btn-outline" id="password-cancel-btn">Cancel</button>
|
||||
<button class="btn btn-primary" id="password-save-btn">
|
||||
<i class="fas fa-key"></i> Update Password
|
||||
</button>
|
||||
</div>
|
||||
@@ -432,15 +387,49 @@
|
||||
let allUsers = [];
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
setupEventListeners();
|
||||
loadUsers();
|
||||
});
|
||||
|
||||
function setupEventListeners() {
|
||||
document.getElementById('add-user-btn')?.addEventListener('click', openAddUserModal);
|
||||
document.getElementById('user-modal-close')?.addEventListener('click', closeModal);
|
||||
document.getElementById('user-cancel-btn')?.addEventListener('click', closeModal);
|
||||
document.getElementById('user-save-btn')?.addEventListener('click', saveUser);
|
||||
|
||||
document.getElementById('password-modal-close')?.addEventListener('click', closePasswordModal);
|
||||
document.getElementById('password-cancel-btn')?.addEventListener('click', closePasswordModal);
|
||||
document.getElementById('password-save-btn')?.addEventListener('click', updatePassword);
|
||||
|
||||
const userBackdrop = document.querySelector('#user-modal .modal-backdrop');
|
||||
userBackdrop?.addEventListener('click', closeModal);
|
||||
|
||||
const passwordBackdrop = document.querySelector('#password-modal .modal-backdrop');
|
||||
passwordBackdrop?.addEventListener('click', closePasswordModal);
|
||||
|
||||
const tbody = document.querySelector('tbody');
|
||||
tbody?.addEventListener('click', function(event) {
|
||||
const actionBtn = event.target.closest('[data-action]');
|
||||
if (!actionBtn) return;
|
||||
|
||||
const { action, id } = actionBtn.dataset;
|
||||
if (action === 'edit' && id) {
|
||||
editUser(id);
|
||||
} else if (action === 'password' && id) {
|
||||
changePassword(id);
|
||||
} else if (action === 'delete' && id) {
|
||||
deleteUser(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function loadUsers() {
|
||||
try {
|
||||
const response = await MSPE.API.get('users.php');
|
||||
if (response && response.success) {
|
||||
allUsers = response.data;
|
||||
renderUsers(allUsers);
|
||||
updateRoleCounts(allUsers);
|
||||
} else {
|
||||
document.querySelector('tbody').innerHTML = '<tr><td colspan="6" class="text-center">Failed to load users</td></tr>';
|
||||
}
|
||||
@@ -450,6 +439,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
function updateRoleCounts(users) {
|
||||
const counts = users.reduce((acc, u) => { acc[u.role] = (acc[u.role] || 0) + 1; return acc; }, {});
|
||||
const adminCount = document.getElementById('count-admin');
|
||||
const editorCount = document.getElementById('count-editor');
|
||||
if (adminCount) adminCount.textContent = `${counts['admin'] || 0} user(s)`;
|
||||
if (editorCount) editorCount.textContent = `${counts['editor'] || 0} user(s)`;
|
||||
}
|
||||
|
||||
function renderUsers(users) {
|
||||
const tbody = document.querySelector('tbody');
|
||||
if (users.length === 0) {
|
||||
@@ -457,36 +454,43 @@
|
||||
return;
|
||||
}
|
||||
|
||||
tbody.innerHTML = users.map(user => `
|
||||
tbody.innerHTML = users.map(user => {
|
||||
const safeName = MSPE.escapeHtml(user.name);
|
||||
const safeUsername = MSPE.escapeHtml(user.username);
|
||||
const safeEmail = MSPE.escapeHtml(user.email);
|
||||
const safeRole = MSPE.escapeHtml(user.role);
|
||||
const safeStatus = MSPE.escapeHtml(user.status);
|
||||
const safeId = MSPE.escapeHtml(user.id);
|
||||
return `
|
||||
<tr>
|
||||
<td>
|
||||
<div class="user-info">
|
||||
<img src="https://ui-avatars.com/api/?name=${encodeURIComponent(user.name)}&background=random" alt="${user.name}">
|
||||
<img src="https://ui-avatars.com/api/?name=${encodeURIComponent(user.name)}&background=random" alt="${safeName}">
|
||||
<div>
|
||||
<span class="name">${user.name}</span>
|
||||
<span class="username">${user.username}</span>
|
||||
<span class="name">${safeName}</span>
|
||||
<span class="username">${safeUsername}</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>${user.email}</td>
|
||||
<td><span class="role-badge ${user.role}">${user.role}</span></td>
|
||||
<td>${safeEmail}</td>
|
||||
<td><span class="role-badge ${safeRole}">${safeRole}</span></td>
|
||||
<td>${user.last_login ? MSPE.formatDate(user.last_login) : 'Never'}</td>
|
||||
<td><span class="status-badge ${user.status}">${user.status}</span></td>
|
||||
<td><span class="status-badge ${safeStatus}">${safeStatus}</span></td>
|
||||
<td>
|
||||
<div class="action-buttons">
|
||||
<button class="btn btn-sm btn-outline" onclick="editUser('${user.id}')">
|
||||
<button class="btn btn-sm btn-outline" data-action="edit" data-id="${safeId}">
|
||||
<i class="fas fa-edit"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline" onclick="changePassword('${user.id}')">
|
||||
<button class="btn btn-sm btn-outline" data-action="password" data-id="${safeId}">
|
||||
<i class="fas fa-key"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-danger" onclick="deleteUser('${user.id}')">
|
||||
<button class="btn btn-sm btn-danger" data-action="delete" data-id="${safeId}">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
</tr>`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function openAddUserModal() {
|
||||
@@ -552,7 +556,21 @@
|
||||
const form = document.getElementById('user-form');
|
||||
const formData = new FormData(form);
|
||||
const id = form.dataset.id;
|
||||
|
||||
|
||||
// Client-side password match check for new users
|
||||
if (!id) {
|
||||
const pw = form.querySelector('[name="password"]').value;
|
||||
const cpw = form.querySelector('[name="password_confirm"]').value;
|
||||
if (pw !== cpw) {
|
||||
MSPE.showNotification('Passwords do not match', 'error');
|
||||
return;
|
||||
}
|
||||
if (pw.length < 12) {
|
||||
MSPE.showNotification('Password must be at least 12 characters', 'error');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (id) formData.append('id', id);
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user