|
|
import React from 'react'; |
|
|
import { saveAs } from 'file-saver'; |
|
|
|
|
|
|
|
|
|
|
|
import { motion } from 'framer-motion'; |
|
|
|
|
|
const Results = ({ result, onReset }) => { |
|
|
if (!result) return null; |
|
|
|
|
|
|
|
|
const score = result.score || 0; |
|
|
const isAI = score > 50; |
|
|
|
|
|
const handleDownload = async () => { |
|
|
try { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const response = await fetch('/api/report/', { |
|
|
method: 'POST', |
|
|
headers: { 'Content-Type': 'application/json' }, |
|
|
body: JSON.stringify({ |
|
|
text: result.originalText || "Content not available", |
|
|
score: score, |
|
|
label: isAI ? "AI Generated" : "Human Written" |
|
|
}) |
|
|
}); |
|
|
|
|
|
if (!response.ok) throw new Error("Report generation failed"); |
|
|
|
|
|
const blob = await response.blob(); |
|
|
saveAs(blob, "DetectAI_Report.pdf"); |
|
|
|
|
|
} catch (e) { |
|
|
alert("Failed to download report: " + e.message); |
|
|
} |
|
|
}; |
|
|
|
|
|
return ( |
|
|
<motion.div |
|
|
initial={{ opacity: 0, scale: 0.95 }} |
|
|
animate={{ opacity: 1, scale: 1 }} |
|
|
className="w-full max-w-3xl glass-panel p-8 mt-6 flex flex-col items-center" |
|
|
> |
|
|
<h2 className="text-2xl font-bold text-white mb-8">Detection Result</h2> |
|
|
|
|
|
<div className="relative w-64 h-32 overflow-hidden mb-6"> |
|
|
{/* Gauge Body */} |
|
|
<div className="absolute top-0 left-0 w-full h-64 rounded-full border-[12px] border-[rgba(255,255,255,0.1)] border-b-transparent rotate-0 box-border pointer-events-none"></div> |
|
|
{/* Gauge Fill */} |
|
|
<motion.div |
|
|
initial={{ rotate: -180 }} |
|
|
animate={{ rotate: -180 + (score / 100) * 180 }} |
|
|
transition={{ duration: 1.5, ease: "circOut" }} |
|
|
className="absolute top-0 left-0 w-full h-64 rounded-full border-[12px] border-b-transparent box-border" |
|
|
style={{ |
|
|
borderColor: `transparent ${isAI ? '#ef4444' : '#22c55e'} ${isAI ? '#ef4444' : '#22c55e'} transparent`, |
|
|
transformOrigin: '50% 50%' |
|
|
}} |
|
|
></motion.div> |
|
|
|
|
|
<div className="absolute bottom-0 left-1/2 transform -translate-x-1/2 mb-4 text-center"> |
|
|
<span className="text-4xl font-bold text-white block">{score.toFixed(1)}%</span> |
|
|
<span className={`text-sm font-uppercase tracking-wider ${isAI ? 'text-red-400' : 'text-green-400'}`}> |
|
|
{isAI ? 'AI GENERATED' : 'HUMAN WRITTEN'} |
|
|
</span> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<p className="text-secondary text-center max-w-md mb-8"> |
|
|
Our DeBERTa model is <strong>{score.toFixed(1)}%</strong> confident that this content was {isAI ? 'generated by AI' : 'written by a human'}. |
|
|
</p> |
|
|
|
|
|
<div className="flex gap-4"> |
|
|
<button |
|
|
onClick={onReset} |
|
|
className="px-6 py-2 border border-[rgba(255,255,255,0.2)] rounded-full text-white hover:bg-[rgba(255,255,255,0.05)] transition-colors" |
|
|
> |
|
|
Analyze Another |
|
|
</button> |
|
|
<button |
|
|
onClick={handleDownload} |
|
|
className="px-6 py-2 bg-blue-600 rounded-full text-white hover:bg-blue-500 transition-colors shadow-lg" |
|
|
> |
|
|
Download PDF Report |
|
|
</button> |
|
|
</div> |
|
|
</motion.div> |
|
|
); |
|
|
}; |
|
|
|
|
|
export default Results; |
|
|
|