Syed Arfan
Add React frontend for Sentiment Analysis API
2857363
raw
history blame
3.49 kB
import { Smile, Frown, Zap, Clock, CheckCircle } from 'lucide-react';
import type { SentimentResult } from '../types';
import { formatConfidence, formatProcessingTime, getConfidenceLevel, truncateText } from '../utils/formatters';
interface ResultCardProps {
result: SentimentResult;
}
const ResultCard = ({ result }: ResultCardProps) => {
const isPositive = result.sentiment === 'POSITIVE';
const confidencePercent = result.confidence * 100;
return (
<div className="animate-slide-up">
<div
className={`rounded-xl p-6 border-2 ${
isPositive
? 'bg-gradient-to-br from-green-50 to-emerald-50 border-green-200'
: 'bg-gradient-to-br from-red-50 to-rose-50 border-red-200'
}`}
>
{/* Main Result */}
<div className="flex items-center gap-4 mb-6">
<div
className={`p-4 rounded-full animate-bounce-subtle ${
isPositive ? 'bg-green-100' : 'bg-red-100'
}`}
>
{isPositive ? (
<Smile className="w-12 h-12 text-green-600" />
) : (
<Frown className="w-12 h-12 text-red-600" />
)}
</div>
<div>
<span
className={`inline-block px-4 py-2 rounded-full text-lg font-bold ${
isPositive
? 'bg-green-500 text-white'
: 'bg-red-500 text-white'
}`}
>
{result.sentiment}
</span>
<p className="mt-2 text-sm text-gray-600">
{getConfidenceLevel(result.confidence)}
</p>
</div>
</div>
{/* Confidence Bar */}
<div className="mb-6">
<div className="flex justify-between items-center mb-2">
<span className="text-sm font-medium text-gray-700">Confidence</span>
<span className="text-lg font-bold font-mono">
{formatConfidence(result.confidence)}
</span>
</div>
<div className="h-3 bg-gray-200 rounded-full overflow-hidden">
<div
className={`h-full rounded-full animate-fill-bar ${
isPositive ? 'bg-green-500' : 'bg-red-500'
}`}
style={{ width: `${confidencePercent}%` }}
/>
</div>
</div>
{/* Metadata */}
<div className="flex flex-wrap gap-4">
<div className="flex items-center gap-2">
{result.cached ? (
<Zap className="w-4 h-4 text-yellow-500" />
) : (
<Clock className="w-4 h-4 text-blue-500" />
)}
<span className="text-sm text-gray-600">
{result.cached ? (
<span className="text-green-600 font-medium">
Cached ({formatProcessingTime(result.processing_time_ms)})
</span>
) : (
<span className="text-blue-600 font-medium">
Processed ({formatProcessingTime(result.processing_time_ms)})
</span>
)}
</span>
</div>
<div className="flex items-center gap-2">
<CheckCircle className="w-4 h-4 text-gray-400" />
<span className="text-sm text-gray-500">
{truncateText(result.text, 50)}
</span>
</div>
</div>
</div>
</div>
);
};
export default ResultCard;