feat: workspace-first UI refresh - PR-2 workspace detail page

- Add workspace detail page (/workspaces/:id) with 4 tabs:
  - Files: file tree, viewer, editor, git toolbar (commit/push/pull/fetch)
  - Git: branch selector, commit history
  - Tools: instance grid, start tool modal
  - Settings: workspace info read-only
- Add workspace API clients: workspace-files, workspace-git, workspace-instances
- Add hooks: useWorkspaceFiles, useWorkspaceGit, useWorkspaceInstances
- WorkspaceCard links to detail page via router Link
- Add comprehensive CSS for workspace detail layout
- Mobile: bottom tab bar, responsive file tree/split
- TypeScript + eslint clean

Quality gates: tsc --noEmit clean, eslint clean
This commit is contained in:
2026-06-01 17:04:44 +02:00
parent e7587ca9f5
commit 27c77af591
12 changed files with 1366 additions and 33 deletions
+45
View File
@@ -0,0 +1,45 @@
/** Workspace file API client. */
import { apiClient } from "./client";
export interface FileEntry {
name: string;
path: string;
type: "file" | "directory";
size?: number;
}
export async function listWorkspaceFiles(
workspaceId: string,
path: string = "",
): Promise<FileEntry[]> {
const response = await apiClient.get<{ entries: FileEntry[] }>(
`/workspaces/${workspaceId}/files/`,
{ params: { path } },
);
return response.data.entries;
}
export async function getWorkspaceFileContent(
workspaceId: string,
path: string,
): Promise<string> {
const response = await apiClient.get<{ content: string }>(
`/workspaces/${workspaceId}/files/content`,
{ params: { path } },
);
return response.data.content;
}
export async function saveWorkspaceFile(
workspaceId: string,
path: string,
content: string,
commitMessage?: string,
): Promise<void> {
await apiClient.post(`/workspaces/${workspaceId}/files/content`, {
path,
content,
message: commitMessage,
});
}