import { useEffect } from "react"; import { useAppStore } from "@/components/state-provider"; import { listWorkflows } from "@/lib/api"; import type { WorkflowsState } from "@/lib/state/slices"; type StoreWorkflow = WorkflowsState["items"][number]; type SetWorkflows = (workflows: StoreWorkflow[]) => void; /** * Fire-and-forget fetch effect. Kept internal so callers that only need to * populate `state.workflows.items` (e.g. `useEnsureWorkspaceWorkflows`) don't * also subscribe to the store slice they wrote to — that would re-render the * caller on every fetch and defeats the "top-level layout" placement. */ function useWorkflowsFetchEffect( workspaceId: string | null, enabled: boolean, setWorkflows: SetWorkflows, ) { useEffect(() => { if (!enabled || !workspaceId) return; let cancelled = false; listWorkflows(workspaceId, { cache: "no-store", includeHidden: true }) .then((response) => { if (cancelled) return; const mapped = response.workflows.map((workflow) => ({ id: workflow.id, workspaceId: workflow.workspace_id, name: workflow.name, description: workflow.description, sortOrder: workflow.sort_order ?? 0, agent_profile_id: workflow.agent_profile_id, hidden: workflow.hidden, style: workflow.style, })); setWorkflows(mapped); }) // Do not clear on error — the sidebar mounts on every route, and boot // hydrates workflows before the refresh fires. Blowing the slice away on // a network flake would leave the sidebar and board with no workflow IDs // until another success. The next successful fetch replaces the slice. .catch(() => {}); return () => { cancelled = true; }; }, [enabled, setWorkflows, workspaceId]); } /** * Load workflows for the active workspace. Call from a component that stays * mounted independently of any collapsible section, so `state.workflows.items` * follows the active workspace even when the sidebar's Tasks section is * collapsed and its children (which consume workflows) are unmounted. */ export function useEnsureWorkspaceWorkflows() { const workspaceId = useAppStore((state) => state.workspaces.activeId); const setWorkflows = useAppStore((state) => state.setWorkflows); useWorkflowsFetchEffect(workspaceId, true, setWorkflows); } export function useWorkflows(workspaceId: string | null, enabled = true) { const workflows = useAppStore((state) => state.workflows.items); const setWorkflows = useAppStore((state) => state.setWorkflows); useWorkflowsFetchEffect(workspaceId, enabled, setWorkflows); return { workflows }; }