"use client"; import { useState, useEffect, useCallback } from "react"; import { WorkflowFile } from "@/store/workflowStore"; import { QuickstartBackButton } from "./QuickstartBackButton"; import { getWorkflowsDirectory, setWorkflowsDirectory, } from "@/store/utils/localStorage"; interface WorkflowListEntry { name: string; directoryPath: string; lastModified: number; } interface WorkflowBrowserViewProps { onBack?: () => void; onWorkflowLoaded: (workflow: WorkflowFile, directoryPath: string) => void; onClose?: () => void; } function formatRelativeTime(timestamp: number): string { const seconds = Math.floor((Date.now() - timestamp) / 1000); if (seconds < 60) return "just now"; const minutes = Math.floor(seconds / 60); if (minutes < 60) return `${minutes}m ago`; const hours = Math.floor(minutes / 60); if (hours < 24) return `${hours}h ago`; const days = Math.floor(hours / 24); if (days < 30) return `${days}d ago`; const months = Math.floor(days / 30); return `${months}mo ago`; } export function WorkflowBrowserView({ onBack, onWorkflowLoaded, onClose, }: WorkflowBrowserViewProps) { const [defaultDir, setDefaultDir] = useState(null); const [workflows, setWorkflows] = useState([]); const [isLoading, setIsLoading] = useState(false); const [loadingWorkflow, setLoadingWorkflow] = useState(null); const [error, setError] = useState(null); useEffect(() => { setDefaultDir(getWorkflowsDirectory()); }, []); const fetchWorkflows = useCallback(async (dirPath: string) => { setIsLoading(true); setError(null); try { const res = await fetch( `/api/list-workflows?path=${encodeURIComponent(dirPath)}` ); const result = await res.json(); if (result.success) { setWorkflows(result.workflows); if (result.workflows.length === 0) { setError("No workflows found in this folder"); } } else { setError(result.error || "Failed to list workflows"); } } catch { setError("Failed to fetch workflows"); } finally { setIsLoading(false); } }, []); // Fetch workflows when default directory is set useEffect(() => { if (defaultDir) { fetchWorkflows(defaultDir); } }, [defaultDir, fetchWorkflows]); const handleChooseFolder = useCallback(async () => { try { const res = await fetch("/api/browse-directory"); const result = await res.json(); if (result.success && !result.cancelled && result.path) { setWorkflowsDirectory(result.path); setDefaultDir(result.path); } } catch { setError("Failed to open directory picker"); } }, []); const handleChangeFolder = useCallback(async () => { try { const res = await fetch("/api/browse-directory"); const result = await res.json(); if (result.success && !result.cancelled && result.path) { setWorkflowsDirectory(result.path); setDefaultDir(result.path); } } catch { setError("Failed to open directory picker"); } }, []); const handleBrowseOther = useCallback(async () => { try { const browseRes = await fetch("/api/browse-directory"); const browseResult = await browseRes.json(); if ( !browseResult.success || browseResult.cancelled || !browseResult.path ) { if (!browseResult.success && !browseResult.cancelled) { setError(browseResult.error || "Failed to open directory picker"); } return; } const dirPath = browseResult.path; setLoadingWorkflow(dirPath); const loadRes = await fetch( `/api/workflow?path=${encodeURIComponent(dirPath)}&load=true` ); const loadResult = await loadRes.json(); setLoadingWorkflow(null); if (!loadResult.success) { setError(loadResult.error || "No workflow file found in directory"); return; } onWorkflowLoaded(loadResult.workflow as WorkflowFile, dirPath); onClose?.(); } catch { setLoadingWorkflow(null); setError("Failed to open workflow"); } }, [onWorkflowLoaded, onClose]); const handleSelectWorkflow = useCallback( async (entry: WorkflowListEntry) => { setLoadingWorkflow(entry.directoryPath); setError(null); try { const res = await fetch( `/api/workflow?path=${encodeURIComponent(entry.directoryPath)}&load=true` ); const result = await res.json(); if (!result.success) { setError(result.error || "Failed to load workflow"); setLoadingWorkflow(null); return; } onWorkflowLoaded( result.workflow as WorkflowFile, entry.directoryPath ); onClose?.(); } catch { setError("Failed to load workflow"); setLoadingWorkflow(null); } }, [onWorkflowLoaded, onClose] ); // State A: No default directory configured if (defaultDir === null) { return (
{onBack && (
)}

Your Workflows

Choose a folder that contains your workflow projects

); } // State B: Default directory configured — show listing return (
{/* Header */}
{onBack && }

Your Workflows

{defaultDir}

{/* Workflow list */}
{isLoading ? (
) : error && workflows.length === 0 ? (

{error}

) : (
{workflows.map((entry) => ( ))}
)} {error && workflows.length > 0 && (

{error}

)}
{/* Footer */}
·
); }