1
0
forked from wrenn/wrenn

Add admin teams management page

Admin panel now includes a Teams page with paginated listing of all teams
(including soft-deleted), BYOC enable with confirmation dialog, and team
deletion with active capsule warnings. Shows member count, owner info,
active capsules, and channel count per team.
This commit is contained in:
2026-04-15 03:36:37 +06:00
parent 587f6ed8ad
commit d332630267
8 changed files with 852 additions and 2 deletions

View File

@ -83,3 +83,39 @@ export async function leaveTeam(id: string): Promise<ApiResult<void>> {
export async function searchUsers(email: string): Promise<ApiResult<UserSearchResult[]>> {
return apiFetch('GET', `/api/v1/users/search?email=${encodeURIComponent(email)}`);
}
// Admin team types and API functions
export type AdminTeam = {
id: string;
name: string;
slug: string;
is_byoc: boolean;
created_at: string;
deleted_at: string | null;
member_count: number;
owner_name: string;
owner_email: string;
active_sandbox_count: number;
channel_count: number;
};
export type AdminTeamsResponse = {
teams: AdminTeam[];
total: number;
page: number;
per_page: number;
total_pages: number;
};
export async function listAdminTeams(page: number = 1): Promise<ApiResult<AdminTeamsResponse>> {
return apiFetch('GET', `/api/v1/admin/teams?page=${page}`);
}
export async function adminSetBYOC(id: string, enabled: boolean): Promise<ApiResult<void>> {
return apiFetch('PUT', `/api/v1/admin/teams/${id}/byoc`, { enabled });
}
export async function adminDeleteTeam(id: string): Promise<ApiResult<void>> {
return apiFetch('DELETE', `/api/v1/admin/teams/${id}`);
}

View File

@ -11,7 +11,8 @@
IconBell,
IconDocs,
IconChevron,
IconShield
IconShield,
IconMembers
} from './icons';
let { collapsed = $bindable(false) }: { collapsed: boolean } = $props();
@ -25,7 +26,8 @@
const managementItems: NavItem[] = [
{ label: 'Templates', icon: IconBox, href: '/admin/templates' },
{ label: 'Capsules', icon: IconMonitor, href: '/admin/capsules' },
{ label: 'Hosts', icon: IconServer, href: '/admin/hosts' }
{ label: 'Hosts', icon: IconServer, href: '/admin/hosts' },
{ label: 'Teams', icon: IconMembers, href: '/admin/teams' }
];
function isActive(href: string): boolean {