// web/js/admin.js
// Dashboard Admin JavaScript - FIXED ENDPOINTS
let allUsers = [];
let allCategories = [];
let allAuditLogs = [];
// Initialize dashboard
window.addEventListener("DOMContentLoaded", async () => {
const user = checkAuth();
if (!user || user.role !== "admin") {
window.location.href = "/login";
return;
}
await loadStats();
await loadUsers();
setupSearchAndFilters();
setupReportFilters();
});
// Load statistics - FIXED
async function loadStats() {
try {
const response = await apiCall("/api/admin/dashboard");
const stats = response.data; // ✅ Access nested data
console.log("Stats received:", stats); // DEBUG
// ✅ Access nested properties correctly
document.getElementById("statTotalUsers").textContent =
stats.users?.total || 0;
document.getElementById("statTotalItems").textContent =
stats.items?.total || 0;
document.getElementById("statTotalClaims").textContent =
stats.claims?.total || 0;
document.getElementById("statTotalArchive").textContent =
stats.archives?.total || 0;
} catch (error) {
console.error("Error loading stats:", error);
showAlert("Gagal memuat statistik", "danger");
}
}
// Load users - CORRECT (sudah sesuai)
async function loadUsers() {
try {
const response = await apiCall("/api/admin/users");
allUsers = response.data || [];
renderUsers(allUsers);
} catch (error) {
console.error("Error loading users:", error);
showAlert("Gagal memuat data user", "danger");
}
}
// Render users
function renderUsers(users) {
const tbody = document.getElementById("usersTableBody");
if (!users || users.length === 0) {
tbody.innerHTML = `
|
Belum ada data user
|
`;
return;
}
tbody.innerHTML = users
.map(
(user) => `
| ${user.name} |
${user.email} |
${user.nrp} |
${getRoleBadge(user.role)} |
${getStatusBadge(user.status || "active")} |
${
user.status === "active"
? ``
: ``
}
|
`
)
.join("");
}
// Edit user
async function editUser(userId) {
try {
const user = await apiCall(`/api/admin/users/${userId}`);
const form = document.getElementById("editUserForm");
form.elements.user_id.value = user.id;
form.elements.name.value = user.name;
form.elements.email.value = user.email;
form.elements.nrp.value = user.nrp;
form.elements.phone.value = user.phone || "";
form.elements.role.value = user.role;
openModal("editUserModal");
} catch (error) {
console.error("Error loading user:", error);
showAlert("Gagal memuat data user", "danger");
}
}
// Submit edit user
document
.getElementById("editUserForm")
?.addEventListener("submit", async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const userId = formData.get("user_id");
const role = formData.get("role");
try {
const submitBtn = e.target.querySelector('button[type="submit"]');
submitBtn.disabled = true;
submitBtn.innerHTML = ' Menyimpan...';
// Update role
await apiCall(`/api/admin/users/${userId}/role`, {
method: "PATCH",
body: JSON.stringify({ role }),
});
showAlert("User berhasil diupdate!", "success");
closeModal("editUserModal");
await loadUsers();
} catch (error) {
console.error("Error updating user:", error);
showAlert(error.message || "Gagal update user", "danger");
} finally {
const submitBtn = e.target.querySelector('button[type="submit"]');
if (submitBtn) {
submitBtn.disabled = false;
submitBtn.textContent = "Update User";
}
}
});
// Block user
async function blockUser(userId) {
if (!confirmAction("Block user ini?")) return;
try {
await apiCall(`/api/admin/users/${userId}/block`, {
method: "POST",
});
showAlert("User berhasil diblock!", "success");
await loadUsers();
} catch (error) {
console.error("Error blocking user:", error);
showAlert(error.message || "Gagal block user", "danger");
}
}
// Unblock user
async function unblockUser(userId) {
if (!confirmAction("Unblock user ini?")) return;
try {
await apiCall(`/api/admin/users/${userId}/unblock`, {
method: "POST",
});
showAlert("User berhasil di-unblock!", "success");
await loadUsers();
} catch (error) {
console.error("Error unblocking user:", error);
showAlert(error.message || "Gagal unblock user", "danger");
}
}
// Load categories
async function loadCategories() {
try {
const response = await apiCall("/api/categories");
allCategories = response.data || [];
renderCategories(allCategories);
} catch (error) {
console.error("Error loading categories:", error);
showAlert("Gagal memuat data kategori", "danger");
}
}
// Render categories
function renderCategories(categories) {
const grid = document.getElementById("categoriesGrid");
if (!categories || categories.length === 0) {
grid.innerHTML = `
`;
return;
}
const icons = {
pakaian: "👕",
alat_makan: "🍽️",
aksesoris: "👓",
elektronik: "💻",
alat_tulis: "✏️",
lainnya: "📦",
};
grid.innerHTML = categories
.map(
(cat) => `
${icons[cat.slug] || "📦"}
${cat.name}
${
cat.description
? `
${cat.description}
`
: ""
}
`
)
.join("");
}
// Submit add category
document
.getElementById("addCategoryForm")
?.addEventListener("submit", async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const data = Object.fromEntries(formData);
try {
const submitBtn = e.target.querySelector('button[type="submit"]');
submitBtn.disabled = true;
submitBtn.innerHTML = ' Menyimpan...';
await apiCall("/api/admin/categories", {
method: "POST",
body: JSON.stringify(data),
});
showAlert("Kategori berhasil ditambahkan!", "success");
closeModal("addCategoryModal");
e.target.reset();
await loadCategories();
} catch (error) {
console.error("Error adding category:", error);
showAlert(error.message || "Gagal menambahkan kategori", "danger");
} finally {
const submitBtn = e.target.querySelector('button[type="submit"]');
if (submitBtn) {
submitBtn.disabled = false;
submitBtn.textContent = "Tambah Kategori";
}
}
});
// Edit category
async function editCategory(catId) {
const newName = prompt("Nama kategori baru:");
if (!newName) return;
try {
await apiCall(`/api/admin/categories/${catId}`, {
method: "PUT",
body: JSON.stringify({ name: newName }),
});
showAlert("Kategori berhasil diupdate!", "success");
await loadCategories();
} catch (error) {
console.error("Error updating category:", error);
showAlert(error.message || "Gagal update kategori", "danger");
}
}
// Delete category
async function deleteCategory(catId) {
if (!confirmAction("Hapus kategori ini?")) return;
try {
await apiCall(`/api/admin/categories/${catId}`, {
method: "DELETE",
});
showAlert("Kategori berhasil dihapus!", "success");
await loadCategories();
} catch (error) {
console.error("Error deleting category:", error);
showAlert(error.message || "Gagal hapus kategori", "danger");
}
}
// Setup report filters - SIMPLIFIED (remove preview)
function setupReportFilters() {
// Remove preview functionality since endpoint doesn't exist
// Just setup the export buttons
}
// Export report
async function exportReport(format) {
const period = document.getElementById("reportPeriod")?.value;
const type = document.getElementById("reportType")?.value;
const startDate = document.getElementById("reportStartDate")?.value;
const endDate = document.getElementById("reportEndDate")?.value;
let url = `/api/admin/reports/export?format=${format}&period=${period}&type=${type}`;
if (period === "custom" && startDate && endDate) {
url += `&start_date=${startDate}&end_date=${endDate}`;
}
try {
const token = getToken();
const response = await fetch(`${API_URL}${url}`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
if (!response.ok) {
throw new Error("Export failed");
}
const blob = await response.blob();
const downloadUrl = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = downloadUrl;
a.download = `laporan_${type}_${period}.${
format === "pdf" ? "pdf" : "xlsx"
}`;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(downloadUrl);
a.remove();
showAlert(
`Laporan ${format.toUpperCase()} berhasil didownload!`,
"success"
);
} catch (error) {
console.error("Error exporting report:", error);
showAlert("Gagal export laporan", "danger");
}
}
// Load audit logs
async function loadAudit() {
try {
const response = await apiCall("/api/admin/audit-logs");
allAuditLogs = response.data || [];
renderAuditLogs(allAuditLogs);
} catch (error) {
console.error("Error loading audit logs:", error);
showAlert("Gagal memuat audit log", "danger");
}
}
// Render audit logs
function renderAuditLogs(logs) {
const tbody = document.getElementById("auditTableBody");
if (!logs || logs.length === 0) {
tbody.innerHTML = `
|
Belum ada audit log
|
`;
return;
}
tbody.innerHTML = logs
.map(
(log) => `
| ${formatDateTime(log.created_at)} |
${log.user_name} |
${log.action} |
${log.details || "-"} |
${log.ip_address || "-"} |
`
)
.join("");
}
// Setup search and filters
function setupSearchAndFilters() {
const searchUsers = document.getElementById("searchUsers");
const roleFilter = document.getElementById("roleFilter");
const statusFilter = document.getElementById("statusFilter");
const performUsersSearch = debounce(() => {
const searchTerm = searchUsers?.value.toLowerCase() || "";
const role = roleFilter?.value || "";
const status = statusFilter?.value || "";
let filtered = allUsers.filter((user) => {
const matchesSearch =
user.name.toLowerCase().includes(searchTerm) ||
user.email.toLowerCase().includes(searchTerm) ||
user.nrp.includes(searchTerm);
const matchesRole = !role || user.role === role;
const matchesStatus = !status || user.status === status;
return matchesSearch && matchesRole && matchesStatus;
});
renderUsers(filtered);
}, 300);
searchUsers?.addEventListener("input", performUsersSearch);
roleFilter?.addEventListener("change", performUsersSearch);
statusFilter?.addEventListener("change", performUsersSearch);
}