"use client"; import { useEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; import { ChevronDown, Folder, MessageSquare, Search, Table2, X, } from "lucide-react"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import type { MikeDocument, MikeWorkflow } from "../shared/types"; import { createTabularReview } from "@/app/lib/mikeApi"; import { useRouter } from "next/navigation"; import { formatIcon, formatLabel } from "../tabular/columnFormat"; import { useDirectoryData } from "../shared/useDirectoryData"; import { FileDirectory } from "../shared/FileDirectory"; import type { MikeProject } from "../shared/types"; import { useChatHistoryContext } from "@/app/contexts/ChatHistoryContext"; interface Props { workflows: MikeWorkflow[]; workflow: MikeWorkflow | null; onClose: () => void; } // --------------------------------------------------------------------------- // Toggle switch // --------------------------------------------------------------------------- function Toggle({ on, onToggle }: { on: boolean; onToggle: () => void }) { return ( ); } // --------------------------------------------------------------------------- // Simple project picker (input + dropdown) // --------------------------------------------------------------------------- function SimpleProjectPicker({ projects, selectedId, onSelect, }: { projects: MikeProject[]; selectedId: string | null; onSelect: (id: string | null) => void; }) { const [search, setSearch] = useState(""); const [open, setOpen] = useState(false); const selected = projects.find((p) => p.id === selectedId); const filtered = search ? projects.filter((p) => p.name.toLowerCase().includes(search.toLowerCase()), ) : projects; return (
{ setSearch(e.target.value); setOpen(true); onSelect(null); }} onFocus={() => setOpen(true)} onBlur={() => setTimeout(() => setOpen(false), 150)} placeholder="Select a project…" className="w-full text-xs text-gray-700 placeholder:text-gray-400 bg-gray-50 border border-gray-200 rounded-md px-3 py-2 outline-none" /> {selectedId && ( )} {open && !selectedId && (
{filtered.length === 0 ? (

No projects found

) : ( filtered.map((p) => ( )) )}
)}
); } // --------------------------------------------------------------------------- // Shared markdown renderer // --------------------------------------------------------------------------- function MarkdownBody({ content }: { content: string }) { return ( (

{children}

), h2: ({ children }) => (

{children}

), h3: ({ children }) => (

{children}

), p: ({ children }) => (

{children}

), ul: ({ children }) => ( ), ol: ({ children }) => (
    {children}
), li: ({ children }) =>
  • {children}
  • , strong: ({ children }) => ( {children} ), em: ({ children }) => {children}, }} > {content}
    ); } // --------------------------------------------------------------------------- // Right panel for assistant workflows (select screen) // --------------------------------------------------------------------------- function AssistantPanel({ workflow }: { workflow: MikeWorkflow }) { return (

    Workflow Prompt

    ); } // --------------------------------------------------------------------------- // Right panel for tabular workflows — accordion column list (select screen) // --------------------------------------------------------------------------- function TabularPanel({ workflow }: { workflow: MikeWorkflow }) { const [expandedIndex, setExpandedIndex] = useState(null); const columns = (workflow.columns_config ?? []).sort( (a, b) => a.index - b.index, ); return (

    Columns

    {columns.length === 0 ? (

    No columns defined

    ) : ( columns.map((col) => { const isExpanded = expandedIndex === col.index; const FormatIcon = formatIcon(col.format ?? "text"); return (
    {isExpanded && (
    {col.tags && col.tags.length > 0 && (

    Tags

    {col.tags.map((tag) => ( {tag} ))}
    )}

    Prompt

    )}
    ); }) )}
    ); } // --------------------------------------------------------------------------- // DisplayWorkflowModal // --------------------------------------------------------------------------- export function DisplayWorkflowModal({ workflows, workflow, onClose }: Props) { const [screen, setScreen] = useState<"select" | "configure">("select"); const [selected, setSelected] = useState(workflow); const [listSearch, setListSearch] = useState(""); const selectedRowRef = useRef(null); // Configure screen state const [inProject, setInProject] = useState(false); const [selectedProjectId, setSelectedProjectId] = useState( null, ); const [selectedDocIds, setSelectedDocIds] = useState>( new Set(), ); const [docSearch, setDocSearch] = useState(""); const [assistantPrompt, setAssistantPrompt] = useState(""); const [saving, setSaving] = useState(false); const router = useRouter(); const { saveChat, setNewChatMessages } = useChatHistoryContext(); const { loading: dirLoading, projects, standaloneDocuments, } = useDirectoryData(screen === "configure"); useEffect(() => { if (workflow) { setSelected(workflow); setScreen("select"); setListSearch(""); } else { setSelected(null); } }, [workflow?.id]); useEffect(() => { if (selected && selectedRowRef.current) { selectedRowRef.current.scrollIntoView({ block: "nearest" }); } }, [selected?.id]); // Reset configure state on back useEffect(() => { if (screen === "select") { setInProject(false); setSelectedProjectId(null); setSelectedDocIds(new Set()); setDocSearch(""); setAssistantPrompt(""); } }, [screen]); function handleClose() { setSelected(null); setScreen("select"); onClose(); } if (!workflow) return null; const wf = selected ?? workflow; // --------------------------------------------------------------------------- // Handlers // --------------------------------------------------------------------------- async function handleStartChat() { setSaving(true); try { const projectId = inProject ? selectedProjectId! : undefined; const chatId = await saveChat(projectId); if (!chatId) return; const allDocs: MikeDocument[] = [ ...standaloneDocuments, ...projects.flatMap((p) => p.documents || []), ]; const files = allDocs .filter((d) => selectedDocIds.has(d.id)) .map((d) => ({ filename: d.filename, document_id: d.id })); const content = assistantPrompt.trim() ? `implement workflow\n\n${assistantPrompt.trim()}` : "implement workflow"; setNewChatMessages([ { role: "user", content, files: files.length > 0 ? files : undefined, }, ]); handleClose(); router.push( projectId ? `/projects/${projectId}/assistant/chat/${chatId}` : `/assistant/chat/${chatId}`, ); } finally { setSaving(false); } } async function handleCreateReview() { const allDocs: MikeDocument[] = [ ...standaloneDocuments, ...projects.flatMap((p) => p.documents || []), ]; const docIds = allDocs .filter((d) => selectedDocIds.has(d.id)) .map((d) => d.id); const projectId = inProject ? selectedProjectId! : undefined; setSaving(true); try { const review = await createTabularReview({ title: wf.title, document_ids: docIds, columns_config: wf.columns_config || [], workflow_id: wf.is_system ? undefined : wf.id, project_id: projectId, }); handleClose(); router.push( projectId ? `/projects/${projectId}/tabular-reviews/${review.id}` : `/tabular-reviews/${review.id}`, ); } finally { setSaving(false); } } // --------------------------------------------------------------------------- // Tabular doc browser helpers // --------------------------------------------------------------------------- const q = docSearch.toLowerCase().trim(); const selectedProject = projects.find((p) => p.id === selectedProjectId); const projectDocs = selectedProject?.documents ?? []; const filteredProjectDocs = q ? projectDocs.filter((d) => d.filename.toLowerCase().includes(q)) : projectDocs; const filteredStandalone = q ? standaloneDocuments.filter((d) => d.filename.toLowerCase().includes(q), ) : standaloneDocuments; const filteredAllProjects = projects .map((p) => ({ ...p, documents: (p.documents || []).filter( (d) => !q || d.filename.toLowerCase().includes(q), ), })) .filter( (p) => !q || p.name.toLowerCase().includes(q) || p.documents.length > 0, ); // --------------------------------------------------------------------------- // Render // --------------------------------------------------------------------------- return createPortal(
    {/* Header */}
    {screen === "select" ? ( <> Workflows Select workflow ) : ( <> {wf.title} {wf.type === "assistant" ? "New Chat" : "New Review"} )}
    {/* ── SELECT SCREEN ── */} {screen === "select" && ( <>
    {/* Left: workflow list */}
    {/* Search */}
    setListSearch(e.target.value)} className="flex-1 bg-transparent text-xs text-gray-700 placeholder:text-gray-400 outline-none" /> {listSearch && ( )}
    {/* List */}
    {workflows .filter((wfItem) => !listSearch || wfItem.title.toLowerCase().includes(listSearch.toLowerCase())) .map((wfItem) => { const isSelected = selected?.id === wfItem.id; const Icon = wfItem.type === "tabular" ? Table2 : MessageSquare; return ( ); })}
    {/* Right: workflow detail */} {wf.type === "assistant" ? ( ) : ( )}
    {wf.is_system ? ( ) : ( )}
    )} {/* ── ASSISTANT CONFIGURE SCREEN ── */} {screen === "configure" && wf.type === "assistant" && ( <>
    {/* Add-on prompt */}

    Message (optional)