96 lines
2.9 KiB
TypeScript
96 lines
2.9 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import { Link } from 'react-router-dom'
|
|
import { Loader2 } from 'lucide-react'
|
|
import { aiSessionsApi } from '@/api'
|
|
import type { SimilarSession } from '@/types/ai-session'
|
|
import { cn } from '@/lib/utils'
|
|
|
|
interface SimilarSessionsProps {
|
|
sessionId: string
|
|
}
|
|
|
|
export function SimilarSessions({ sessionId }: SimilarSessionsProps) {
|
|
const [sessions, setSessions] = useState<SimilarSession[]>([])
|
|
const [loading, setLoading] = useState(true)
|
|
|
|
useEffect(() => {
|
|
let cancelled = false
|
|
setLoading(true)
|
|
aiSessionsApi
|
|
.getSimilar(sessionId, 5)
|
|
.then((data) => {
|
|
if (!cancelled) setSessions(data)
|
|
})
|
|
.catch(() => {
|
|
// Silently ignore errors — don't clutter the UI
|
|
})
|
|
.finally(() => {
|
|
if (!cancelled) setLoading(false)
|
|
})
|
|
return () => {
|
|
cancelled = true
|
|
}
|
|
}, [sessionId])
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="flex items-center gap-1.5 py-1">
|
|
<Loader2 size={10} className="animate-spin text-[#848b9b]" />
|
|
<span className="text-[0.625rem] text-[#848b9b] font-sans text-xs">Loading similar sessions…</span>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (sessions.length === 0) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-2">
|
|
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">
|
|
Similar Past Sessions
|
|
</h4>
|
|
{sessions.map((session) => (
|
|
<Link
|
|
key={session.id}
|
|
to={`/pilot/${session.id}`}
|
|
className="card-interactive p-3 block hover:border-[rgba(255,255,255,0.12)] transition-all"
|
|
>
|
|
<div className="flex items-start justify-between gap-2">
|
|
<p className="text-xs text-[#e2e5eb] line-clamp-2">
|
|
{session.problem_summary || 'Untitled session'}
|
|
</p>
|
|
<span className="text-[0.625rem] font-sans text-xs text-[#22d3ee] shrink-0">
|
|
{Math.round(session.similarity * 100)}%
|
|
</span>
|
|
</div>
|
|
{session.resolution_summary && (
|
|
<p className="text-[0.625rem] text-[#848b9b] mt-1 line-clamp-1">
|
|
✓ {session.resolution_summary}
|
|
</p>
|
|
)}
|
|
<div className="flex items-center gap-2 mt-1.5">
|
|
{session.problem_domain && (
|
|
<span className="text-[0.5rem] font-sans text-xs uppercase tracking-wider text-[#848b9b]/70">
|
|
{session.problem_domain}
|
|
</span>
|
|
)}
|
|
<span
|
|
className={cn(
|
|
'text-[0.5rem] font-sans text-xs uppercase',
|
|
session.status === 'resolved'
|
|
? 'text-emerald-400'
|
|
: session.status === 'escalated'
|
|
? 'text-amber-400'
|
|
: 'text-[#848b9b]'
|
|
)}
|
|
>
|
|
{session.status}
|
|
</span>
|
|
</div>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|