import { Plan } from "@vertesia/common"; import { AlertCircle, CheckCircle, Circle, Clock } from "lucide-react"; import { useUITranslation } from '../../../../i18n/index.js'; import SlideInPanel from "./SlideInPanel"; interface PlanPanelProps { plan?: Plan; workstreamStatus: Map; isOpen: boolean; onClose: () => void; } export default function SlidingPlanPanel({ plan, workstreamStatus, isOpen, onClose }: PlanPanelProps) { const { t } = useUITranslation(); return ( plan && ( {/* Plan Summary */}
{t('agent.planProgress')}
status === "completed", ).length / Math.max(1, workstreamStatus.size)) * 100, ) : 0 }%`, }} />
{plan.plan && plan.plan.length ? `${Array.from(workstreamStatus.values()).filter((status) => status === "completed").length}/${workstreamStatus.size}` : "0/0"}
{/* Detailed Plan Steps */}
{t('agent.stepByStepPlan')}
{plan.plan && plan.plan.length > 0 ? ( plan.plan.map((task, index) => { // Extract task info with null checks const taskId = task.id ? task.id.toString() : `task-${index}`; const taskGoal = task.goal || `Task ${index + 1}`; // Determine task status - use task.status if available or lookup from workstream let status: "pending" | "in_progress" | "completed" | "skipped" = task.status || "pending"; if (workstreamStatus.has(taskId)) { status = workstreamStatus.get(taskId)!; } // Determine status icon and style let StatusIcon = Circle; let statusColor = "text-gray-400"; let bgColor = ""; if (status === "in_progress") { StatusIcon = Clock; statusColor = "text-blue-500"; bgColor = "bg-blue-50/50 dark:bg-blue-900/10"; } else if (status === "completed") { StatusIcon = CheckCircle; statusColor = "text-green-500"; } return (
{taskGoal}
{taskId} {status === "completed" ? t('agent.completed') : status === "in_progress" ? t('agent.inProgress') : t('agent.pending')}
); }) ) : (

{t('agent.noPlanDetected')}

{t('agent.plansWillAppear')}

)}
{/* Workstream Status Summary */} {workstreamStatus.size > 1 && (
{t('agent.workstreams')}
{Array.from(workstreamStatus.entries()) // Filter to only show real workstreams (main or those with valid names - not numeric IDs) .filter(([id, _]) => { // Always show 'main' workstream if (id === "main") return true; // Don't show if it's a pure numeric ID (likely a task) if (/^\d+$/.test(id)) return false; // Don't show workstreams that are actually tasks (have matching IDs in plan) if (plan?.plan) { const matchingTask = plan.plan.find((task) => task.id?.toString() === id); return !matchingTask; // Keep if no matching task found } return true; }) .map(([id, status]) => { let StatusIcon = Circle; let statusColor = "text-gray-400"; let statusBg = "bg-gray-100 dark:bg-gray-800"; let statusText = t('agent.pending'); if (status === "in_progress") { StatusIcon = Clock; statusColor = "text-blue-500"; statusBg = "bg-blue-100 dark:bg-blue-800/30"; statusText = t('agent.inProgress'); } else if (status === "completed") { StatusIcon = CheckCircle; statusColor = "text-green-500"; statusBg = "bg-green-100 dark:bg-green-800/30"; statusText = t('agent.completed'); } // Format workstream IDs for better display const displayId = id === "main" ? t('agent.mainWorkstream') : id; return (
{displayId}
{statusText}
); })}
)} ) ); }