73 lines
2.0 KiB
TypeScript
73 lines
2.0 KiB
TypeScript
import { fetchAdminList } from "@/lib/admin-list";
|
|
import { canAccess, PERMS } from "@/lib/permissions";
|
|
import { CreateUserDialog } from "./_components/create-user-dialog";
|
|
import { UsersTable } from "./users-table";
|
|
|
|
export default async function UsersPage({
|
|
params: paramsPromise,
|
|
searchParams,
|
|
}: {
|
|
params: Promise<{ locale: string }>;
|
|
searchParams: Promise<Record<string, string>>;
|
|
}) {
|
|
const result = await fetchAdminList(
|
|
{
|
|
permission: PERMS.USERS_VIEW,
|
|
model: "user",
|
|
searchFields: ["username", "mail", "ipRegister", "ipCurrent"],
|
|
select: {
|
|
id: true,
|
|
username: true,
|
|
mail: true,
|
|
rank: true,
|
|
credits: true,
|
|
pixels: true,
|
|
online: true,
|
|
motto: true,
|
|
look: true,
|
|
ipRegister: true,
|
|
accountCreated: true,
|
|
lastLogin: true,
|
|
},
|
|
filterMap: {
|
|
filter_rank: (v) => {
|
|
const n = Number(v);
|
|
if (!Number.isFinite(n)) return null;
|
|
// For rank 7 the preset means "super admins" — match ≥ 7 instead of equals.
|
|
return n >= 7 ? { rank: { gte: 7 } } : { rank: n };
|
|
},
|
|
filter_online: (v) => ({ online: v }),
|
|
},
|
|
},
|
|
paramsPromise,
|
|
searchParams,
|
|
);
|
|
|
|
const canEdit = canAccess(result.permissions, PERMS.USERS_EDIT, result.rank);
|
|
const canBan = canAccess(result.permissions, PERMS.USERS_BAN, result.rank);
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h1 className="text-3xl font-bold tracking-tight">Users</h1>
|
|
<p className="text-muted-foreground">{result.total.toLocaleString()} users total</p>
|
|
</div>
|
|
{canEdit && <CreateUserDialog sessionRank={result.rank} />}
|
|
</div>
|
|
|
|
<UsersTable
|
|
data={{
|
|
rows: result.rows,
|
|
total: result.total,
|
|
page: result.page,
|
|
perPage: result.perPage,
|
|
lastPage: result.lastPage,
|
|
}}
|
|
canEdit={canEdit}
|
|
canBan={canBan}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|