updateweb
This commit is contained in:
352
website/admin/js/users.js
Normal file
352
website/admin/js/users.js
Normal file
@@ -0,0 +1,352 @@
|
||||
// User Management JavaScript
|
||||
|
||||
let usersData = [];
|
||||
let userModal;
|
||||
let passwordModal;
|
||||
|
||||
const rolePermissions = {
|
||||
Cashier: ["View Products", "Process Orders", "View Customers"],
|
||||
Accountant: [
|
||||
"View Products",
|
||||
"View Orders",
|
||||
"View Reports",
|
||||
"View Financial Data",
|
||||
],
|
||||
Admin: [
|
||||
"Manage Products",
|
||||
"Manage Portfolio",
|
||||
"Manage Blog",
|
||||
"Manage Pages",
|
||||
"Manage Users",
|
||||
"View Reports",
|
||||
],
|
||||
MasterAdmin: [
|
||||
"Full System Access",
|
||||
"Manage Settings",
|
||||
"Manage Users",
|
||||
"Manage All Content",
|
||||
"View Logs",
|
||||
"System Configuration",
|
||||
],
|
||||
};
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
userModal = new bootstrap.Modal(document.getElementById("userModal"));
|
||||
passwordModal = new bootstrap.Modal(document.getElementById("passwordModal"));
|
||||
checkAuth().then((authenticated) => {
|
||||
if (authenticated) {
|
||||
loadUsers();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
async function loadUsers() {
|
||||
try {
|
||||
const response = await fetch("/api/admin/users", {
|
||||
credentials: "include",
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
usersData = data.users;
|
||||
renderUsers(usersData);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to load users:", error);
|
||||
}
|
||||
}
|
||||
|
||||
function renderUsers(users) {
|
||||
const tbody = document.getElementById("usersTableBody");
|
||||
if (users.length === 0) {
|
||||
tbody.innerHTML = `
|
||||
<tr><td colspan="8" class="text-center p-4">
|
||||
<i class="bi bi-inbox" style="font-size: 3rem; color: #ccc;"></i>
|
||||
<p class="mt-3 text-muted">No users found</p>
|
||||
<button class="btn btn-primary" onclick="showCreateUser()">
|
||||
<i class="bi bi-person-plus"></i> Create First User
|
||||
</button>
|
||||
</td></tr>`;
|
||||
return;
|
||||
}
|
||||
|
||||
tbody.innerHTML = users
|
||||
.map(
|
||||
(u) => `
|
||||
<tr>
|
||||
<td>${u.id}</td>
|
||||
<td><strong>${escapeHtml(u.name)}</strong></td>
|
||||
<td>${escapeHtml(u.email)}</td>
|
||||
<td>@${escapeHtml(u.username)}</td>
|
||||
<td><span class="role-badge role-${u.role
|
||||
.toLowerCase()
|
||||
.replace(" ", "-")}">${u.role}</span></td>
|
||||
<td><span class="badge ${u.isactive ? "badge-success" : "badge-danger"}">
|
||||
${u.isactive ? "Active" : "Disabled"}</span></td>
|
||||
<td>${formatDate(u.createdat)}</td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-info" onclick="editUser(${
|
||||
u.id
|
||||
})" title="Edit User">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-warning" onclick="showChangePassword(${
|
||||
u.id
|
||||
}, '${escapeHtml(u.name)}')" title="Change Password">
|
||||
<i class="bi bi-key"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-danger" onclick="deleteUser(${
|
||||
u.id
|
||||
}, '${escapeHtml(u.name)}')" title="Delete User">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>`
|
||||
)
|
||||
.join("");
|
||||
}
|
||||
|
||||
function filterUsers() {
|
||||
const searchTerm = document.getElementById("searchInput").value.toLowerCase();
|
||||
const filtered = usersData.filter(
|
||||
(u) =>
|
||||
u.name.toLowerCase().includes(searchTerm) ||
|
||||
u.email.toLowerCase().includes(searchTerm) ||
|
||||
u.username.toLowerCase().includes(searchTerm)
|
||||
);
|
||||
renderUsers(filtered);
|
||||
}
|
||||
|
||||
function showCreateUser() {
|
||||
document.getElementById("modalTitle").textContent = "Create New User";
|
||||
document.getElementById("userForm").reset();
|
||||
document.getElementById("userId").value = "";
|
||||
document.getElementById("userActive").checked = true;
|
||||
document.getElementById("userPasswordNeverExpires").checked = false;
|
||||
document.getElementById("userRole").value = "Cashier";
|
||||
updatePermissionsPreview();
|
||||
userModal.show();
|
||||
}
|
||||
|
||||
async function editUser(id) {
|
||||
try {
|
||||
const response = await fetch(`/api/admin/users/${id}`, {
|
||||
credentials: "include",
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
const user = data.user;
|
||||
document.getElementById("modalTitle").textContent = "Edit User";
|
||||
document.getElementById("userId").value = user.id;
|
||||
document.getElementById("userName").value = user.name;
|
||||
document.getElementById("userUsername").value = user.username;
|
||||
document.getElementById("userEmail").value = user.email;
|
||||
document.getElementById("userPassword").value = "";
|
||||
document.getElementById("userPasswordConfirm").value = "";
|
||||
document.getElementById("userRole").value = user.role;
|
||||
document.getElementById("userActive").checked = user.isactive;
|
||||
document.getElementById("userPasswordNeverExpires").checked =
|
||||
user.passwordneverexpires || false;
|
||||
updatePermissionsPreview();
|
||||
userModal.show();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to load user:", error);
|
||||
showError("Failed to load user details");
|
||||
}
|
||||
}
|
||||
|
||||
async function saveUser() {
|
||||
const id = document.getElementById("userId").value;
|
||||
const password = document.getElementById("userPassword").value;
|
||||
const passwordConfirm = document.getElementById("userPasswordConfirm").value;
|
||||
|
||||
// Password validation (only for new users or when changing password)
|
||||
if (!id || password) {
|
||||
if (!password) {
|
||||
showError("Password is required for new users");
|
||||
return;
|
||||
}
|
||||
if (password !== passwordConfirm) {
|
||||
showError("Passwords do not match");
|
||||
return;
|
||||
}
|
||||
if (password.length < 8) {
|
||||
showError("Password must be at least 8 characters long");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const formData = {
|
||||
name: document.getElementById("userName").value,
|
||||
username: document.getElementById("userUsername").value,
|
||||
email: document.getElementById("userEmail").value,
|
||||
role: document.getElementById("userRole").value,
|
||||
isactive: document.getElementById("userActive").checked,
|
||||
passwordneverexpires: document.getElementById("userPasswordNeverExpires")
|
||||
.checked,
|
||||
};
|
||||
|
||||
if (password) {
|
||||
formData.password = password;
|
||||
}
|
||||
|
||||
if (!formData.name || !formData.username || !formData.email) {
|
||||
showError("Please fill in all required fields");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const url = id ? `/api/admin/users/${id}` : "/api/admin/users";
|
||||
const method = id ? "PUT" : "POST";
|
||||
const response = await fetch(url, {
|
||||
method: method,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
body: JSON.stringify(formData),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
showSuccess(
|
||||
id ? "User updated successfully" : "User created successfully"
|
||||
);
|
||||
userModal.hide();
|
||||
loadUsers();
|
||||
} else {
|
||||
showError(data.message || "Failed to save user");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to save user:", error);
|
||||
showError("Failed to save user");
|
||||
}
|
||||
}
|
||||
|
||||
function showChangePassword(id, name) {
|
||||
document.getElementById("passwordUserId").value = id;
|
||||
document.getElementById("passwordUserName").value = name;
|
||||
document.getElementById("passwordUserDisplay").textContent = name;
|
||||
document.getElementById("passwordForm").reset();
|
||||
passwordModal.show();
|
||||
}
|
||||
|
||||
async function changePassword() {
|
||||
const id = document.getElementById("passwordUserId").value;
|
||||
const newPassword = document.getElementById("newPassword").value;
|
||||
const confirmPassword = document.getElementById("confirmNewPassword").value;
|
||||
|
||||
if (!newPassword || !confirmPassword) {
|
||||
showError("Please enter and confirm the new password");
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPassword !== confirmPassword) {
|
||||
showError("Passwords do not match");
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPassword.length < 8) {
|
||||
showError("Password must be at least 8 characters long");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/admin/users/${id}/password`, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
body: JSON.stringify({ password: newPassword }),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
showSuccess("Password changed successfully");
|
||||
passwordModal.hide();
|
||||
} else {
|
||||
showError(data.message || "Failed to change password");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to change password:", error);
|
||||
showError("Failed to change password");
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteUser(id, name) {
|
||||
if (
|
||||
!confirm(
|
||||
`Are you sure you want to delete user "${name}"? This action cannot be undone.`
|
||||
)
|
||||
)
|
||||
return;
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/admin/users/${id}`, {
|
||||
method: "DELETE",
|
||||
credentials: "include",
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
showSuccess("User deleted successfully");
|
||||
loadUsers();
|
||||
} else {
|
||||
showError(data.message || "Failed to delete user");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to delete user:", error);
|
||||
showError("Failed to delete user");
|
||||
}
|
||||
}
|
||||
|
||||
function updatePermissionsPreview() {
|
||||
const role = document.getElementById("userRole").value;
|
||||
const permissions = rolePermissions[role] || [];
|
||||
const container = document.getElementById("permissionsPreview");
|
||||
|
||||
container.innerHTML = permissions
|
||||
.map(
|
||||
(perm) => `
|
||||
<div class="permission-item active">
|
||||
<i class="bi bi-check-circle-fill" style="color: #10b981; margin-right: 8px;"></i>
|
||||
<span>${perm}</span>
|
||||
</div>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
try {
|
||||
const response = await fetch("/api/admin/logout", {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
});
|
||||
if (response.ok) window.location.href = "/admin/login.html";
|
||||
} catch (error) {
|
||||
console.error("Logout failed:", error);
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
const map = {
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
'"': """,
|
||||
"'": "'",
|
||||
};
|
||||
return text.replace(/[&<>"']/g, (m) => map[m]);
|
||||
}
|
||||
|
||||
function formatDate(dateString) {
|
||||
return new Date(dateString).toLocaleDateString("en-US", {
|
||||
year: "numeric",
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
});
|
||||
}
|
||||
|
||||
function showSuccess(message) {
|
||||
alert(message);
|
||||
}
|
||||
function showError(message) {
|
||||
alert("Error: " + message);
|
||||
}
|
||||
Reference in New Issue
Block a user