Spaces:
Running
Running
File size: 2,885 Bytes
4939f56 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | 'use client';
import { motion } from 'framer-motion';
import { FileText, ArrowSquareOut as ExternalLink } from '@phosphor-icons/react';
import type { FinalSynthesisReport } from '@/types/pipeline';
import { fadeUp } from '@/lib/animations';
import { ConfidenceBadge } from '@/components/results/ConfidenceBadge';
const TOOL_LABELS: Record<string, string> = {
blast: 'BLAST',
uniprot: 'UniProt',
domains: 'Domains',
msa: 'MSA',
pathway_enrichment: 'Pathways',
alphafold: 'Structure',
};
interface FinalReportProps {
data: FinalSynthesisReport;
}
export function FinalReport({ data }: FinalReportProps) {
if (!data || !data.findings?.length) return null;
return (
<motion.div variants={fadeUp} className="data-card p-6">
<div className="flex items-start justify-between gap-4 mb-3">
<div>
<h2 className="text-lg font-semibold text-text-primary flex items-center gap-2">
<FileText className="w-5 h-5 text-accent-cyan" />
Final Report
</h2>
<p className="text-sm text-text-secondary mt-1">{data.headline}</p>
</div>
{data._mode === 'llm_polished' && (
<span className="text-[10px] uppercase tracking-wider text-text-muted border border-glass-border rounded px-1.5 py-0.5 shrink-0">
AI-polished
</span>
)}
</div>
{data.summary && data.summary !== data.headline && (
<p className="text-sm text-text-secondary leading-relaxed mb-4">{data.summary}</p>
)}
<div className="space-y-2 mt-4">
{data.findings.map((f, i) => (
<div key={i} className="flex items-start justify-between gap-3 bg-surface-1 rounded-lg px-3 py-2">
<div className="text-sm text-text-secondary leading-relaxed min-w-0">
{f.claim}
{f.page_url && (
<a
href={f.page_url}
target="_blank"
rel="noopener noreferrer"
className="ml-1.5 text-accent-cyan hover:text-accent-cyan/80 inline-flex items-center gap-0.5"
title={`Source page: ${f.page_url}`}
>
source <ExternalLink className="w-3 h-3" />
</a>
)}
<span className="text-xs text-text-muted ml-2">({TOOL_LABELS[f.source_tool] ?? f.source_tool})</span>
</div>
<ConfidenceBadge confidence={f.confidence_tier} className="shrink-0 scale-90 origin-right" />
</div>
))}
</div>
{data.caveats?.length > 0 && (
<div className="mt-4 pt-4 border-t border-glass-border">
{data.caveats.map((c, i) => (
<p key={i} className="text-xs text-text-muted leading-relaxed mt-1 first:mt-0">
{c}
</p>
))}
</div>
)}
</motion.div>
);
}
|