chore: initial project scaffold with admin web, backend, desktop client, and deployment setup
Add monorepo structure for NexaVPN WireGuard control plane including: - .gitignore for node_modules, build artifacts, and environment files - README with project overview, monorepo layout, and quick start guide - Admin web UI with React, Vite, TypeScript, and nginx reverse proxy - API client with type definitions for users, devices, policies, gateways, and audit logs - Admin pages for dashboard, users, devices, policies, g
This commit is contained in:
41
admin-web/src/features/users/UsersPage.tsx
Normal file
41
admin-web/src/features/users/UsersPage.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
import { api } from "../../api/client";
|
||||
import { Page } from "../../components/Page";
|
||||
import { Table } from "../../components/Table";
|
||||
|
||||
const columns = [
|
||||
{ key: "username", label: "Username" },
|
||||
{ key: "name", label: "Display name" },
|
||||
{ key: "role", label: "Role" },
|
||||
{ key: "status", label: "Status" }
|
||||
];
|
||||
|
||||
export function UsersPage() {
|
||||
const query = useQuery({
|
||||
queryKey: ["users"],
|
||||
queryFn: api.users
|
||||
});
|
||||
|
||||
const rows = query.data?.map((user) => ({
|
||||
username: user.username,
|
||||
name: user.display_name,
|
||||
role: user.role,
|
||||
status: user.is_active ? "active" : "disabled"
|
||||
})) ?? [];
|
||||
|
||||
return (
|
||||
<Page
|
||||
title="Users"
|
||||
subtitle="Create, disable, and manage platform identities."
|
||||
actions={<button className="button">New user</button>}
|
||||
>
|
||||
{query.isError ? <p className="notice">Unable to load users from the API.</p> : null}
|
||||
<Table
|
||||
columns={columns}
|
||||
rows={rows}
|
||||
renderCell={(row, column) => <span>{row[column.key as keyof (typeof rows)[number]]}</span>}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user