112 lines
4.1 KiB
JavaScript
112 lines
4.1 KiB
JavaScript
// assets/js/pages/admin/tabs/UsersTab.js
|
|
|
|
const UsersTab = ({ state, handlers }) => {
|
|
const {
|
|
searchTerm,
|
|
setSearchTerm,
|
|
roleFilter,
|
|
setRoleFilter,
|
|
statusFilter,
|
|
setStatusFilter,
|
|
filteredUsers,
|
|
currentPage,
|
|
totalPages,
|
|
totalRecords,
|
|
setCurrentPage,
|
|
} = state;
|
|
|
|
const { handleEditUser, handleBlockUser, handleUnblockUser } = handlers;
|
|
|
|
return (
|
|
<div className="bg-gradient-to-br from-slate-800 to-slate-900 rounded-xl shadow-xl border border-slate-700">
|
|
<div className="p-6 border-b border-slate-700">
|
|
<h2 className="text-xl font-semibold mb-4 text-white">Daftar User</h2>
|
|
|
|
<div className="flex gap-3 flex-wrap">
|
|
<input
|
|
type="text"
|
|
placeholder="Cari user..."
|
|
value={searchTerm}
|
|
onChange={(e) => setSearchTerm(e.target.value)}
|
|
className="flex-1 min-w-[200px] px-4 py-2 bg-slate-700 border-2 border-slate-600 rounded-xl text-white placeholder-slate-400 focus:border-blue-500 focus:outline-none"
|
|
/>
|
|
<select
|
|
value={roleFilter}
|
|
onChange={(e) => setRoleFilter(e.target.value)}
|
|
className="px-4 py-2 bg-slate-700 border-2 border-slate-600 rounded-xl text-white focus:border-blue-500 focus:outline-none"
|
|
>
|
|
<option value="">Semua Role</option>
|
|
<option value="user">User</option>
|
|
<option value="manager">Manager</option>
|
|
<option value="admin">Admin</option>
|
|
</select>
|
|
<select
|
|
value={statusFilter}
|
|
onChange={(e) => setStatusFilter(e.target.value)}
|
|
className="px-4 py-2 bg-slate-700 border-2 border-slate-600 rounded-xl text-white focus:border-blue-500 focus:outline-none"
|
|
>
|
|
<option value="">Semua Status</option>
|
|
<option value="active">Active</option>
|
|
<option value="blocked">Blocked</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="overflow-x-auto">
|
|
<table className="min-w-full divide-y divide-slate-700">
|
|
<thead className="bg-slate-900/50">
|
|
<tr>
|
|
<th className="px-6 py-3 text-left text-xs font-medium text-slate-400 uppercase tracking-wider">
|
|
Nama
|
|
</th>
|
|
<th className="px-6 py-3 text-left text-xs font-medium text-slate-400 uppercase tracking-wider">
|
|
Email
|
|
</th>
|
|
<th className="px-6 py-3 text-left text-xs font-medium text-slate-400 uppercase tracking-wider">
|
|
NRP
|
|
</th>
|
|
<th className="px-6 py-3 text-left text-xs font-medium text-slate-400 uppercase tracking-wider">
|
|
Role
|
|
</th>
|
|
<th className="px-6 py-3 text-left text-xs font-medium text-slate-400 uppercase tracking-wider">
|
|
Status
|
|
</th>
|
|
<th className="px-6 py-3 text-left text-xs font-medium text-slate-400 uppercase tracking-wider">
|
|
Aksi
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="bg-gradient-to-br from-slate-800 to-slate-900 divide-y divide-slate-700">
|
|
{filteredUsers.map((u) => (
|
|
<UserRow
|
|
key={u.id}
|
|
user={u}
|
|
onEdit={handleEditUser}
|
|
onBlock={handleBlockUser}
|
|
onUnblock={handleUnblockUser}
|
|
/>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{filteredUsers.length > 0 && (
|
|
<Pagination
|
|
currentPage={currentPage}
|
|
totalPages={totalPages}
|
|
totalRecords={totalRecords}
|
|
onPageChange={(page) => setCurrentPage(page)}
|
|
itemsPerPage={CONFIG.PAGINATION.LIMIT}
|
|
/>
|
|
)}
|
|
|
|
{filteredUsers.length === 0 && (
|
|
<div className="text-center py-12 text-slate-400">
|
|
<div className="text-6xl mb-4">👥</div>
|
|
<p>Tidak ada user ditemukan</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|