'use client'; import { ChevronRight, GitBranch, ArrowRight, Copy, Check } from 'lucide-react'; import { Badge } from '@/components/ui/badge'; import { cn } from '@/lib/utils'; import { useState } from 'react'; export interface Hop { from: string; rel: string; to: string; doc?: string; } interface PathViewProps { hops: Hop[]; conclusion?: string; alternativePaths?: Hop[][]; hopCount?: number; entityA?: string; entityB?: string; standalone?: boolean; } export function PathView({ hops, conclusion, alternativePaths = [], hopCount, entityA, entityB, standalone = false, }: PathViewProps) { const [copied, setCopied] = useState(false); const [activeTab, setActiveTab] = useState(0); if (!hops || hops.length === 0) return null; const totalHops = hopCount ?? hops.length; const handleCopy = () => { const text = hops .map((h) => `${h.from} --[${h.rel.replace(/_/g, ' ')}]--> ${h.to}`) .join('\n'); navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 2000); }; const renderChain = (chain: Hop[], index?: number) => (
{index !== undefined && (

Alternative Path {index + 1}

)}
{chain.map((hop, i) => (
{hop.from} {hop.doc && {hop.doc}}
{hop.rel.replace(/_/g, ' ')}
{i === chain.length - 1 && (
{hop.to}
)}
))}
); const renderStandalone = () => (
{/* Header */}
Multi-Hop Reasoning Path
{totalHops} hop{totalHops !== 1 ? 's' : ''}
{/* Entity pair header */} {entityA && entityB && (
{entityA} {entityB}
)} {/* Vertical timeline layout */}
{hops.map((hop, i) => (
{/* Timeline line */}
{i + 1}
{i < hops.length - 1 && (
)}
{/* Hop content */}
{hop.from} {hop.rel.replace(/_/g, ' ')} {hop.to}
{hop.doc && (

Source: {hop.doc}

)}
))}
{/* Alternative paths tabs */} {alternativePaths.length > 0 && (
{alternativePaths.map((_, i) => ( ))}
{activeTab === 0 && renderChain(hops)} {activeTab > 0 && renderChain(alternativePaths[activeTab - 1], activeTab)}
)} {/* Conclusion */} {conclusion && (
Conclusion: {conclusion}
)}
); // Compact mode (default — used in Query page) return (
Multi-Hop Reasoning Path
{renderChain(hops)} {alternativePaths.length > 0 && alternativePaths.map((p, i) => renderChain(p, i + 1))} {conclusion && (
Conclusion: {conclusion}
)}
); }