Spaces:
Paused
Paused
Nawaz-khan-droid
build: finalize stratos refactor, textarea hardening, and payload limit alignment
acf82bb | import React, { useState } from 'react'; | |
| import { ChevronDown, ChevronUp, Video } from 'lucide-react'; | |
| export default function OutputPanel({ result }) { | |
| const [showTranscript, setShowTranscript] = useState(false); | |
| if (!result) return null; | |
| const confidence = (result.confidence || 0) * 100; | |
| const transcriptPreview = result.video_transcript || ''; | |
| const getConfidenceColor = (c) => { | |
| if (c >= 80) return 'text-emerald-400'; | |
| if (c >= 60) return 'text-sky-400'; | |
| if (c >= 40) return 'text-amber-400'; | |
| return 'text-rose-400'; | |
| }; | |
| return ( | |
| <div className="glass-card animate-fade-in space-y-5 p-6"> | |
| <div className="flex items-center justify-between gap-4"> | |
| <h3 className="text-lg font-semibold text-white">Analysis Result</h3> | |
| <span className={`text-sm font-medium ${getConfidenceColor(confidence)}`}>{confidence.toFixed(1)}% confidence</span> | |
| </div> | |
| {result.answer && ( | |
| <div className="space-y-2"> | |
| <h4 className="text-xs uppercase tracking-wider text-slate-500">Summary</h4> | |
| <p className="text-sm leading-relaxed text-slate-200" style={{ overflowWrap: 'break-word', wordBreak: 'break-word' }}>{result.answer}</p> | |
| </div> | |
| )} | |
| {result.context_summary && ( | |
| <div className="space-y-2"> | |
| <h4 className="text-xs uppercase tracking-wider text-slate-500">Verification Context</h4> | |
| <p className="text-sm leading-relaxed text-slate-300" style={{ overflowWrap: 'break-word', wordBreak: 'break-word' }}>{result.context_summary}</p> | |
| </div> | |
| )} | |
| {transcriptPreview && ( | |
| <div className="mt-6 border-t border-white/10 pt-6"> | |
| <button | |
| type="button" | |
| onClick={() => setShowTranscript((prev) => !prev)} | |
| className="flex w-full items-center justify-between gap-3 text-left transition-colors hover:text-sky-200" | |
| > | |
| <div className="flex items-center gap-2"> | |
| <Video className="h-4 w-4 text-sky-400" /> | |
| <div> | |
| <h4 className="text-xs uppercase tracking-wider text-sky-300">Video Transcript</h4> | |
| <p className="text-xs text-slate-500">{showTranscript ? 'Hide transcript details' : 'Expand transcript details'}</p> | |
| </div> | |
| </div> | |
| {showTranscript ? <ChevronUp className="h-4 w-4 text-sky-300" /> : <ChevronDown className="h-4 w-4 text-sky-300" />} | |
| </button> | |
| {showTranscript && ( | |
| <div | |
| className="custom-scrollbar max-h-[350px] overflow-y-auto rounded-lg border border-sky-500/20 bg-slate-950/40 p-4 text-sm leading-relaxed text-slate-300 whitespace-pre-wrap" | |
| style={{ overflowWrap: 'break-word', wordBreak: 'break-word' }} | |
| > | |
| {transcriptPreview} | |
| </div> | |
| )} | |
| </div> | |
| )} | |
| {result.metadata?.input_type === 'url' && result.metadata?.extraction?.safety_warning && ( | |
| <div className="rounded-lg border border-red-500/20 bg-red-500/10 p-3"> | |
| <p className="text-xs text-red-400">Safety Warning: {Array.isArray(result.metadata.extraction.safety_warning) ? result.metadata.extraction.safety_warning.join(', ') : result.metadata.extraction.safety_warning}</p> | |
| </div> | |
| )} | |
| {result.agreements && result.agreements.length > 0 && ( | |
| <div className="space-y-2"> | |
| <h4 className="text-xs uppercase tracking-wider text-slate-500">Corroborating Sources</h4> | |
| <div className="flex flex-wrap gap-2"> | |
| {result.agreements.map((source, i) => ( | |
| <span key={i} className="rounded-full border border-emerald-400/20 bg-emerald-500/10 px-2 py-1 text-xs text-emerald-300">{source}</span> | |
| ))} | |
| </div> | |
| </div> | |
| )} | |
| {result.compute_time_ms && ( | |
| <p className="text-xs text-slate-600">Processed in {result.compute_time_ms}ms across {result.metadata?.sources_retrieved || 0} sources</p> | |
| )} | |
| </div> | |
| ); | |
| } | |