// 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 stats = await apiCall("/api/admin/dashboard"); document.getElementById("statTotalUsers").textContent = stats.total_users || 0; document.getElementById("statTotalItems").textContent = stats.total_items || 0; document.getElementById("statTotalClaims").textContent = stats.total_claims || 0; document.getElementById("statTotalArchive").textContent = stats.total_archive || 0; } catch (error) { console.error("Error loading stats:", error); } } // 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 = `
🏷️

Belum ada kategori

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