"use client"; import { useEffect, useState } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Skeleton } from "@/components/ui/skeleton"; import { CheckCircle2, AlertTriangle, HelpCircle, Users, Lightbulb, Wrench, AlertCircle, Sparkles } from "lucide-react"; import { cn } from "@/lib/utils"; interface ExtractionHandoff { phase: string; readyForNextPhase: boolean; confidence: number; confirmed: { problems?: string[]; targetUsers?: string[]; features?: string[]; constraints?: string[]; opportunities?: string[]; }; uncertain: Record; missing: string[]; questionsForUser: string[]; timestamp: string; } interface ExtractionResultsProps { projectId: string; className?: string; } export function ExtractionResults({ projectId, className }: ExtractionResultsProps) { const [extraction, setExtraction] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchExtraction = async () => { try { setLoading(true); const response = await fetch(`/api/projects/${projectId}/extraction-handoff`); if (!response.ok) { if (response.status === 404) { setExtraction(null); return; } throw new Error(`Failed to fetch extraction: ${response.statusText}`); } const data = await response.json(); setExtraction(data.handoff); } catch (err) { console.error("[ExtractionResults] Error:", err); setError(err instanceof Error ? err.message : "Failed to load extraction"); } finally { setLoading(false); } }; if (projectId) { fetchExtraction(); } }, [projectId]); if (loading) { return (
); } if (error) { return (

{error}

); } if (!extraction) { return (

No extraction results yet

Upload documents and trigger extraction to see insights

); } const { confirmed } = extraction; const confidencePercent = Math.round(extraction.confidence * 100); return (
{/* Header with Confidence Score */}
Extraction Results
{extraction.readyForNextPhase ? ( <> Ready ) : ( <> Incomplete )} = 70 ? "border-green-500 text-green-600" : confidencePercent >= 40 ? "border-yellow-500 text-yellow-600" : "border-red-500 text-red-600" )}> {confidencePercent}% confidence

Extracted on {new Date(extraction.timestamp).toLocaleString()}

{/* Problems / Pain Points */} {confirmed.problems && confirmed.problems.length > 0 && ( Problems & Pain Points {confirmed.problems.length}
    {confirmed.problems.map((problem, idx) => (
  • {problem}
  • ))}
)} {/* Target Users */} {confirmed.targetUsers && confirmed.targetUsers.length > 0 && ( Target Users {confirmed.targetUsers.length}
    {confirmed.targetUsers.map((user, idx) => (
  • {user}
  • ))}
)} {/* Features */} {confirmed.features && confirmed.features.length > 0 && ( Key Features {confirmed.features.length}
    {confirmed.features.map((feature, idx) => (
  • {feature}
  • ))}
)} {/* Constraints */} {confirmed.constraints && confirmed.constraints.length > 0 && ( Constraints & Requirements {confirmed.constraints.length}
    {confirmed.constraints.map((constraint, idx) => (
  • {constraint}
  • ))}
)} {/* Opportunities */} {confirmed.opportunities && confirmed.opportunities.length > 0 && ( Opportunities {confirmed.opportunities.length}
    {confirmed.opportunities.map((opportunity, idx) => (
  • {opportunity}
  • ))}
)} {/* Missing Information */} {extraction.missing && extraction.missing.length > 0 && ( Missing Information
    {extraction.missing.map((item, idx) => (
  • - {item}
  • ))}
)} {/* Questions for User */} {extraction.questionsForUser && extraction.questionsForUser.length > 0 && ( Questions for Clarification
    {extraction.questionsForUser.map((question, idx) => (
  • {idx + 1}. {question}
  • ))}
)}
); }