"use client" import { useCallback, useEffect, useMemo, useState } from "react" import { CheckCircle2Icon, GitBranchIcon, SaveIcon, SendIcon } from "lucide-react" import { toast } from "sonner" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Textarea } from "@/components/ui/textarea" import { createAIWorkflow, fetchAIWorkflowNodeSpecs, fetchAIWorkflows, publishAIWorkflow, updateAIWorkflow, validateAIWorkflow, type AIWorkflow, type AIWorkflowDefinition, type AIWorkflowNodeSpec, type AIWorkflowValidationResult, } from "@/lib/api/admin" import { WorkflowEditor } from "./_components/workflow-editor" const emptyDefinition: AIWorkflowDefinition = { schemaVersion: 1, entryNodeId: "start_1", nodes: [ { id: "start_1", type: "start", name: "Start", position: { x: 0, y: 80 }, config: {}, }, { id: "end_1", type: "end", name: "End", position: { x: 360, y: 80 }, config: {}, }, ], edges: [{ id: "edge_start_end", source: "start_1", target: "end_1" }], } export default function DashboardAIWorkflowsPage() { const [workflows, setWorkflows] = useState([]) const [nodeSpecs, setNodeSpecs] = useState([]) const [selected, setSelected] = useState(null) const [name, setName] = useState("Customer support flow") const [description, setDescription] = useState("") const [ownerId, setOwnerId] = useState("1") const [definition, setDefinition] = useState(emptyDefinition) const [validation, setValidation] = useState(null) const [loading, setLoading] = useState(false) const editorKey = useMemo( () => `${selected?.id ?? "new"}-${selected?.updatedAt ?? ""}`, [selected?.id, selected?.updatedAt] ) const loadData = useCallback(async () => { const [workflowPage, specs] = await Promise.all([ fetchAIWorkflows({ page: 1, limit: 50, status: 0 }), fetchAIWorkflowNodeSpecs(), ]) setWorkflows(workflowPage?.results ?? []) setNodeSpecs(specs ?? []) }, []) useEffect(() => { void loadData().catch((error) => { toast.error(error instanceof Error ? error.message : "Failed to load workflows") }) }, [loadData]) const selectWorkflow = (workflow: AIWorkflow) => { setSelected(workflow) setName(workflow.name) setDescription(workflow.description) setOwnerId(String(workflow.ownerId || 1)) setDefinition(workflow.draftDefinition ?? emptyDefinition) setValidation(null) } const createNew = () => { setSelected(null) setName("Customer support flow") setDescription("") setOwnerId("1") setDefinition(emptyDefinition) setValidation(null) } const saveDraft = async () => { setLoading(true) try { const payload = { name, description, ownerType: "ai_agent", ownerId: Number(ownerId) || 0, definition, } if (selected) { await updateAIWorkflow({ id: selected.id, ...payload }) toast.success("Draft saved") } else { const created = await createAIWorkflow(payload) setSelected(created) toast.success("Workflow created") } await loadData() } catch (error) { toast.error(error instanceof Error ? error.message : "Failed to save workflow") } finally { setLoading(false) } } const runValidation = async () => { setLoading(true) try { const result = await validateAIWorkflow(definition) setValidation(result) toast[result.valid ? "success" : "error"]( result.valid ? "Workflow is valid" : "Workflow has validation errors" ) } catch (error) { toast.error(error instanceof Error ? error.message : "Failed to validate workflow") } finally { setLoading(false) } } const publish = async () => { if (!selected) { toast.error("Save the workflow before publishing.") return } setLoading(true) try { const version = await publishAIWorkflow(selected.id, definition) toast.success(`Published version ${version.version}`) await loadData() } catch (error) { toast.error(error instanceof Error ? error.message : "Failed to publish workflow") } finally { setLoading(false) } } return (

AI Workflows

Edit and publish customer-service conversation flows.