feat(web): wire workspace member management UI (MS21-UI-004) (#577)
All checks were successful
ci/woodpecker/push/web Pipeline was successful

Co-authored-by: Jason Woltje <jason@diversecanvas.com>
Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #577.
This commit is contained in:
2026-02-28 22:12:05 +00:00
committed by jason.woltje
parent 307639eca0
commit e93e7ffaa9
3 changed files with 240 additions and 188 deletions

View File

@@ -4,12 +4,8 @@
*/
import type { WorkspaceMemberRole } from "@mosaic/shared";
import { apiGet, apiPost } from "./client";
import { apiDelete, apiGet, apiPatch, apiPost } from "./client";
/**
* A workspace entry from the user's membership list.
* Matches WorkspaceResponseDto from the API.
*/
export interface UserWorkspace {
id: string;
name: string;
@@ -32,17 +28,57 @@ export interface CreatedWorkspace {
memberCount: number;
}
/**
* Fetch all workspaces the authenticated user is a member of.
* The API auto-provisions a default workspace if the user has none.
*/
export interface WorkspaceMemberUser {
id: string;
email: string;
name: string | null;
image: string | null;
}
export interface WorkspaceMemberEntry {
workspaceId: string;
userId: string;
role: WorkspaceMemberRole;
joinedAt: string;
user: WorkspaceMemberUser;
}
export interface AddMemberDto {
userId: string;
role: WorkspaceMemberRole;
}
export interface UpdateMemberRoleDto {
role: WorkspaceMemberRole;
}
export async function fetchUserWorkspaces(): Promise<UserWorkspace[]> {
return apiGet<UserWorkspace[]>("/api/workspaces");
}
/**
* Create a workspace through the admin endpoint.
*/
export async function createWorkspace(dto: CreateWorkspaceDto): Promise<CreatedWorkspace> {
return apiPost<CreatedWorkspace>("/api/admin/workspaces", dto);
}
export async function fetchWorkspaceMembers(workspaceId: string): Promise<WorkspaceMemberEntry[]> {
return apiGet<WorkspaceMemberEntry[]>(`/api/workspaces/${workspaceId}/members`);
}
export async function addWorkspaceMember(
workspaceId: string,
dto: AddMemberDto
): Promise<WorkspaceMemberEntry> {
return apiPost<WorkspaceMemberEntry>(`/api/workspaces/${workspaceId}/members`, dto);
}
export async function updateWorkspaceMemberRole(
workspaceId: string,
userId: string,
dto: UpdateMemberRoleDto
): Promise<WorkspaceMemberEntry> {
return apiPatch<WorkspaceMemberEntry>(`/api/workspaces/${workspaceId}/members/${userId}`, dto);
}
export async function removeWorkspaceMember(workspaceId: string, userId: string): Promise<void> {
await apiDelete<unknown>(`/api/workspaces/${workspaceId}/members/${userId}`);
}