Files
headquarter/apps/web/src/hooks/use-repo-workspace.ts
T
Developer 6b118307eb refactor: extract RepoWorkspacePage components
- Extract use-repo-workspace hook for data loading
- Extract WorkspaceLayout and FileBrowser components
- Slim RepoWorkspacePage from 505 to ~80 lines

Quality gates: tsc --noEmit passes, npm run build passes
2026-06-05 19:43:13 +00:00

149 lines
4.2 KiB
TypeScript

import { useCallback, useEffect, useState } from "react";
import { useParams, useSearchParams } from "react-router-dom";
import { apiClient } from "../api/client";
import {
getRepositoryStatus,
listRepositories,
type GitRepository,
type GitStatus,
} from "../api/git-repositories";
import { listToolTypes, type ToolType } from "../api/tool-types";
type WorkspaceStatus = "loading" | "ready" | "error" | "empty";
export interface Project {
id: string;
name: string;
description?: string | null;
}
export const useRepoWorkspace = () => {
const { projectId } = useParams<{ projectId: string }>();
const [searchParams, setSearchParams] = useSearchParams();
const [status, setStatus] = useState<WorkspaceStatus>("loading");
const [project, setProject] = useState<Project | null>(null);
const [repositories, setRepositories] = useState<GitRepository[]>([]);
const [selectedRepoId, setSelectedRepoId] = useState<string | null>(
searchParams.get("repo")
);
const [branches, setBranches] = useState<string[]>([]);
const [currentBranch, setCurrentBranch] = useState<string>("main");
const [gitStatus, setGitStatus] = useState<GitStatus | null>(null);
const [toolTypes, setToolTypes] = useState<ToolType[]>([]);
const loadProject = useCallback(async () => {
if (!projectId) return;
try {
const response = await apiClient.get(`/projects/${projectId}`);
setProject(response.data);
} catch {
setProject(null);
}
}, [projectId]);
const loadRepositories = useCallback(async () => {
if (!projectId) return;
setStatus("loading");
try {
const data = await listRepositories(projectId);
setRepositories(data);
if (data.length === 0) {
setStatus("empty");
} else {
setStatus("ready");
if (!selectedRepoId) {
setSelectedRepoId(data[0].id);
const newParams = new URLSearchParams(searchParams);
newParams.set("repo", data[0].id);
setSearchParams(newParams, { replace: true });
}
}
} catch {
setRepositories([]);
setStatus("error");
}
}, [projectId, selectedRepoId, searchParams, setSearchParams]);
const loadBranches = useCallback(async () => {
if (!projectId || !selectedRepoId) return;
try {
const response = await apiClient.get(
`/projects/${projectId}/repositories/${selectedRepoId}/branches`
);
const branchList = response.data.branches.map((b: { name: string }) => b.name);
setBranches(branchList);
const defaultBranch = response.data.default_branch;
if (defaultBranch) setCurrentBranch(defaultBranch);
} catch {
setBranches([]);
}
}, [projectId, selectedRepoId]);
const loadGitStatus = useCallback(async () => {
if (!projectId || !selectedRepoId) return;
try {
const data = await getRepositoryStatus(projectId, selectedRepoId);
setGitStatus(data);
} catch {
setGitStatus(null);
}
}, [projectId, selectedRepoId]);
const loadToolTypes = useCallback(async () => {
try {
const data = await listToolTypes();
setToolTypes(data);
} catch {
setToolTypes([]);
}
}, []);
useEffect(() => {
void loadProject();
void loadRepositories();
void loadToolTypes();
}, [loadProject, loadRepositories, loadToolTypes]);
useEffect(() => {
void loadBranches();
void loadGitStatus();
}, [loadBranches, loadGitStatus]);
const handleRepoChange = (repoId: string) => {
setSelectedRepoId(repoId);
const newParams = new URLSearchParams(searchParams);
newParams.set("repo", repoId);
newParams.delete("branch");
newParams.delete("path");
setSearchParams(newParams);
};
const handleBranchChange = (branch: string) => {
setCurrentBranch(branch);
const newParams = new URLSearchParams(searchParams);
newParams.set("branch", branch);
setSearchParams(newParams);
};
const selectedRepo = repositories.find((r) => r.id === selectedRepoId);
return {
projectId,
project,
status,
repositories,
selectedRepoId,
selectedRepo,
branches,
currentBranch,
gitStatus,
toolTypes,
handleRepoChange,
handleBranchChange,
loadGitStatus,
loadBranches,
loadRepositories,
};
};