// 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}

{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"));