// assets/js/pages/admin/AdminApp.js - WITH CATEGORIES TAB
const { useState, useEffect } = React;
const AdminApp = () => {
const state = useAdminState();
const handlers = useAdminHandlers(state);
const {
user,
setUser,
activeTab,
setActiveTab,
stats,
users,
setFilteredUsers,
currentPage,
searchTerm,
roleFilter,
statusFilter,
showEditModal,
setShowEditModal,
selectedUser,
toast,
setToast,
loading,
showItemDetailModal,
setShowItemDetailModal,
selectedItemDetail,
showClaimDetailModal,
setShowClaimDetailModal,
selectedClaim,
showArchiveDetailModal,
setShowArchiveDetailModal,
selectedArchive,
} = state;
const { loadData, loadItems, showToast, handleUpdateUser } = handlers;
useEffect(() => {
if (!AuthUtils.checkAuthAndRedirect("admin")) return;
const currentUser = AuthUtils.getCurrentUser();
setUser(currentUser);
loadData();
handlers.loadCategories(); // ✅ Load categories on mount
}, []);
useEffect(() => {
if (user) {
loadData(); // Ini memuat Users menggunakan currentPage (sudah benar di handler)
loadItems();
handlers.loadClaims();
handlers.loadArchives();
// ✅ PERBAIKAN: Kirim currentPage agar tidak reset ke 1
handlers.loadAuditLogs(currentPage);
}
}, [user, currentPage]);
useEffect(() => {
if (currentPage !== 1) {
state.setCurrentPage(1);
} else {
filterUsers();
}
}, [searchTerm, roleFilter, statusFilter]);
useEffect(() => {
filterUsers();
}, [users]);
useEffect(() => {
filterItemsData();
}, [
state.itemSearchTerm,
state.itemStatusFilter,
state.itemCategoryFilter,
state.items,
]);
const filterUsers = () => {
let filtered = users.filter((u) => {
const matchesSearch =
u.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
u.email.toLowerCase().includes(searchTerm.toLowerCase()) ||
u.nrp.includes(searchTerm);
const matchesRole = !roleFilter || u.role === roleFilter;
const matchesStatus =
!statusFilter || (u.status || "active") === statusFilter;
return matchesSearch && matchesRole && matchesStatus;
});
setFilteredUsers(filtered);
};
const filterItemsData = () => {
let filtered = state.items.filter((item) => {
const matchesSearch =
item.name.toLowerCase().includes(state.itemSearchTerm.toLowerCase()) ||
item.location
.toLowerCase()
.includes(state.itemSearchTerm.toLowerCase());
const matchesStatus =
!state.itemStatusFilter || item.status === state.itemStatusFilter;
const matchesCategory =
!state.itemCategoryFilter ||
Helpers.getCategoryValue(item.category_id) === state.itemCategoryFilter;
return matchesSearch && matchesStatus && matchesCategory;
});
state.setFilteredItems(filtered);
};
return (
Dashboard Admin
Kelola sistem Lost & Found
{/* Stats */}
{/* Tabs */}
{/* ✅ NEW: Categories Tab */}
{/* Tab Content */}
{activeTab === "users" && window.UsersTab && (
)}
{activeTab === "roles" && window.RolesTab && (
)}
{activeTab === "items" && window.ItemsTab && (
)}
{activeTab === "lostitems" && window.LostItemsTabAdmin && (
<>
{window.CreateLostItemModal && (
)}
{window.EditLostItemModal && (
)}
{window.LostItemDetailModal && (
)}
>
)}
{activeTab === "claims" && window.ClaimsTabAdmin && (
)}
{activeTab === "categories" && window.CategoriesTab && (
)}
{activeTab === "archives" && window.ArchivesTabAdmin && (
)}
{activeTab === "audit-log" && window.AuditLogTab && (
)}
{activeTab === "reports" && window.ReportsTab && (
)}
{/* Modals */}
{window.ClaimDetailModalAdmin && (
setShowClaimDetailModal(false)}
claim={selectedClaim}
/>
)}
{window.ArchiveDetailModal && (
setShowArchiveDetailModal(false)}
archive={selectedArchive}
/>
)}
{window.RoleModal && (
<>
state.setShowCreateRoleModal(false)}
allPermissions={state.permissions}
onSubmit={handlers.handleCreateRole}
loading={loading}
/>
{
state.setShowEditRoleModal(false);
state.setSelectedRole(null);
}}
role={state.selectedRole}
allPermissions={state.permissions}
onSubmit={handlers.handleUpdateRole}
loading={loading}
/>
>
)}
{window.CreateClaimModal && (
)}
{window.EditClaimModal && (
)}
{/* Edit User Modal */}
setShowEditModal(false)}
title="Edit User"
>
{selectedUser && (
)}
{/* Item Detail Modal */}
setShowItemDetailModal(false)}
title="Detail Barang"
>
{selectedItemDetail && (
{selectedItemDetail.name}
Kategori:
{selectedItemDetail.category ||
Helpers.getCategoryName(selectedItemDetail.category_id)}
Lokasi:
{selectedItemDetail.location}
Tanggal Ditemukan:
{Helpers.formatDate(selectedItemDetail.date_found)}
Status:
{selectedItemDetail.status}
Deskripsi Umum:
{selectedItemDetail.description || "Tidak ada deskripsi"}
Pelapor:
{selectedItemDetail.reporter_name || "Tidak ada data"}
Kontak Pelapor:
{selectedItemDetail.reporter_contact || "Tidak ada data"}
🔒
Ciri Khusus Rahasia (Untuk Verifikasi)
{selectedItemDetail.secret_details ||
"Tidak ada deskripsi rahasia"}
⚠️ Info ini RAHASIA - gunakan untuk verifikasi klaim
{selectedItemDetail.case_closed_at && (
📋
Case Closed
{selectedItemDetail.berita_acara_no && (
No. BA:{" "}
{selectedItemDetail.berita_acara_no}
)}
Ditutup:{" "}
{Helpers.formatDateTime(
selectedItemDetail.case_closed_at
)}
{selectedItemDetail.case_closed_by_name && (
Oleh: {selectedItemDetail.case_closed_by_name}
)}
{selectedItemDetail.case_closed_notes && (
Catatan: {selectedItemDetail.case_closed_notes}
)}
{selectedItemDetail.bukti_serah_terima && (
📄 Lihat Bukti
)}
)}
)}
{/* Toast */}
{toast && (
setToast(null)}
/>
)}
{/* AI Chatbot */}
);
};
// Render
ReactDOM.render(, document.getElementById("root"));