/** Hook for workspace CRUD actions with confirmation handling. */ import { useState, useCallback } from "react"; import { createWorkspace, deleteWorkspace, syncWorkspace, updateWorkspace, } from "../api/workspaces"; import type { Workspace, CreateWorkspaceRequest } from "../types/workspace"; export interface UseWorkspaceActionsResult { loadingId: string | null; create: ( projectId: string, repoId: string, data: CreateWorkspaceRequest, ) => Promise; delete: ( workspace: Workspace, onRefresh: () => Promise, ) => Promise; sync: ( projectId: string, repoId: string, workspace: Workspace, onRefresh: () => Promise, ) => Promise; update: ( projectId: string, repoId: string, workspaceId: string, data: Partial, ) => Promise; } interface ApiError { response?: { status?: number; data?: { detail?: { message?: string; instances?: Array<{ id: string; name: string }>; branch_deleted?: boolean; }; }; }; } export function useWorkspaceActions(): UseWorkspaceActionsResult { const [loadingId, setLoadingId] = useState(null); const create = useCallback( async (projectId: string, repoId: string, data: CreateWorkspaceRequest) => { return createWorkspace(projectId, repoId, data); }, [], ); const deleteAction = useCallback( async (workspace: Workspace, onRefresh: () => Promise) => { setLoadingId(workspace.id); try { await deleteWorkspace(workspace.id); await onRefresh(); } catch (err) { const error = err as ApiError; if (error.response?.status === 409) { const detail = error.response.data?.detail; const instances = detail?.instances || []; const confirmed = window.confirm( `This workspace has ${instances.length} running tool instance(s):\n` + instances.map((i) => `- ${i.name}`).join("\n") + `\n\nDelete workspace and all instances?`, ); if (confirmed) { await deleteWorkspace(workspace.id, true); await onRefresh(); } } else { throw err; } } finally { setLoadingId(null); } }, [], ); const sync = useCallback( async ( projectId: string, repoId: string, workspace: Workspace, onRefresh: () => Promise, ) => { setLoadingId(workspace.id); try { await syncWorkspace(projectId, repoId, workspace.id); await onRefresh(); } catch (err) { const error = err as ApiError; if ( error.response?.status === 409 && error.response.data?.detail?.branch_deleted ) { const message = error.response.data.detail.message || "Branch was deleted from remote"; const confirmed = window.confirm( `${message}\n\nDelete this workspace?`, ); if (confirmed) { await deleteWorkspace(workspace.id, true); await onRefresh(); } } else { throw err; } } finally { setLoadingId(null); } }, [], ); const update = useCallback( async ( projectId: string, repoId: string, workspaceId: string, data: Partial, ) => { return updateWorkspace(projectId, repoId, workspaceId, data); }, [], ); return { loadingId, create, delete: deleteAction, sync, update, }; }