feat: workspace frontend core (PR-3)

- Workspace types, API client, hooks (useWorkspaces, useWorkspaceActions)
- WorkspaceCard, WorkspaceCreateForm, StartToolModal components
- WorkspacesPage with list, create, sync, delete, start-tool flow
- Sidebar navigation: new 'Workspaces' entry
- Router: /workspaces route
- TypeScript + eslint clean
This commit is contained in:
2026-05-31 23:27:10 +02:00
parent 47b1af8e92
commit 986091ac56
10 changed files with 623 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
/** Hook for fetching workspaces. */
import { useCallback, useEffect, useState } from "react";
import { listWorkspaces } from "../api/workspaces";
import type { Workspace } from "../types/workspace";
export interface UseWorkspacesResult {
workspaces: Workspace[];
loading: boolean;
error: string | null;
refresh: () => Promise<void>;
}
export function useWorkspaces(projectId: string, repoId: string): UseWorkspacesResult {
const [workspaces, setWorkspaces] = useState<Workspace[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const refresh = useCallback(async () => {
setLoading(true);
setError(null);
try {
const data = await listWorkspaces(projectId, repoId);
setWorkspaces(data);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to load workspaces");
} finally {
setLoading(false);
}
}, [projectId, repoId]);
useEffect(() => {
refresh();
}, [refresh]);
return { workspaces, loading, error, refresh };
}