refactor: extract dashboard, workspace, tool-types, and tool-configs components (Task 4.3)

- Extract DashboardSummary, ActiveSessionsList, ProjectsSection, QuickCreateForm,
  RecentSessionsSection from dashboard.tsx (480 → 110 lines)
- Extract WorkspaceSidebar from repo-workspace.tsx
- Extract ToolTypeList + ToolTypeForm from tool-types.tsx (409 → 135 lines)
- Extract ToolConfigList + ToolConfigForm from tool-configs.tsx (391 → 178 lines)
- Add use-dashboard-actions hook for shared dashboard action handlers
- Update feature barrels with new exports

Quality gates: tsc (pass), eslint (pass)
Refs: repo-restructure Task 4.3
This commit is contained in:
Developer
2026-06-02 22:23:13 +00:00
parent 6bd7443e68
commit a6eb6ec788
32 changed files with 1583 additions and 1104 deletions
+115
View File
@@ -0,0 +1,115 @@
import { useState, useCallback } from "react";
import { useNavigate } from "react-router-dom";
import {
createInstance,
startInstance,
stopInstance,
deleteInstance,
recreateInstanceTunnel,
} from "../api/sessions";
import { updateUserConfig } from "../api/settings";
import type { Session } from "../types/session";
export function useDashboardActions(onRefresh: () => Promise<void>) {
const navigate = useNavigate();
const [saveState, setSaveState] = useState<"idle" | "saving" | "error">("idle");
const [actionBusy, setActionBusy] = useState<string | null>(null);
const handleCreate = useCallback(
async (data: {
projectId: string;
repoId: string;
toolTypeId: string;
displayName: string;
}) => {
setSaveState("saving");
try {
const instance = await createInstance(
data.projectId,
data.repoId,
data.toolTypeId,
data.displayName || undefined,
);
await startInstance(data.projectId, data.repoId, instance.id);
await updateUserConfig({ last_session_id: instance.id });
setSaveState("idle");
await onRefresh();
} catch {
setSaveState("error");
}
},
[onRefresh],
);
const handleOpen = useCallback(
(session: Session) => {
if (session.url) {
window.open(session.url, "_blank", "noopener,noreferrer");
return;
}
if (session.tool_type_interfaces.includes("terminal")) {
navigate(`/instances/${session.id}/terminal`);
return;
}
navigate(`/projects/${session.project_id}`);
},
[navigate],
);
const handleStop = useCallback(
async (session: Session) => {
setActionBusy(session.id);
try {
await stopInstance(session.project_id, session.repository_id, session.id);
await onRefresh();
} finally {
setActionBusy(null);
}
},
[onRefresh],
);
const handleDelete = useCallback(
async (session: Session) => {
setActionBusy(session.id);
try {
await deleteInstance(
session.project_id,
session.repository_id,
session.id,
);
await onRefresh();
} finally {
setActionBusy(null);
}
},
[onRefresh],
);
const handleRecreateTunnel = useCallback(
async (session: Session) => {
setActionBusy(session.id);
try {
await recreateInstanceTunnel(
session.project_id,
session.repository_id,
session.id,
);
await onRefresh();
} finally {
setActionBusy(null);
}
},
[onRefresh],
);
return {
saveState,
actionBusy,
handleCreate,
handleOpen,
handleStop,
handleDelete,
handleRecreateTunnel,
};
}