Spotix-API / frontend /components /dashboard /AnalyticsSection.tsx
Anish
[Minor changes to Frontend]
825fa02
import React, { useMemo } from 'react';
import { PieChart, Pie, Cell, Tooltip, ResponsiveContainer, BarChart, Bar, XAxis, YAxis, Tooltip as BarTooltip } from 'recharts';
export default function AnalyticsSection({ files }: { files: any[] }) {
const stats = useMemo(() => {
const total = files.length;
if (!total) return { pieData: [], barData: [], summary: { total: 0, ai: 0, real: 0 } };
let aiCount = 0;
let realCount = 0;
let suspCount = 0;
// Group by Date for Bar Chart
const dateMap: Record<string, number> = {};
files.forEach(f => {
const resStr = (f.result || "").toUpperCase();
if (resStr.includes('AI') || resStr.includes('FAKE')) aiCount++;
else if (resStr.includes('REAL') || resStr.includes('AUTHENTIC')) realCount++;
else suspCount++;
// Use uploaded_at if available, otherwise just use a generic 'Today' bucket for mapping
const dateObj = f.uploaded_at ? new Date(f.uploaded_at) : new Date();
const dateStr = dateObj.toLocaleDateString();
dateMap[dateStr] = (dateMap[dateStr] || 0) + 1;
});
const pieData = [
{ name: 'AI Detected', value: aiCount, color: '#ef4444' },
{ name: 'Authentic', value: realCount, color: '#22c55e' },
{ name: 'Suspicious', value: suspCount, color: '#eab308' }
].filter(d => d.value > 0);
// Sort dates chronologically for Bar Chart
const barData = Object.keys(dateMap).sort((a,b) => new Date(a).getTime() - new Date(b).getTime()).map(k => ({
date: k,
uploads: dateMap[k]
}));
const aiPercent = Math.round((aiCount / total) * 100);
const realPercent = Math.round((realCount / total) * 100);
return { pieData, barData, summary: { total, ai: aiPercent, real: realPercent } };
}, [files]);
if (!files.length) return null;
return (
<div className="w-full relative z-10 mb-12">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{/* Quick Stats Column */}
<div className="flex flex-col gap-6 lg:col-span-1">
<div className="p-6 bg-[var(--theme-text)]/5 border border-[var(--theme-border)] rounded-2xl dash-border hover:bg-[var(--theme-text)]/10 transition backdrop-blur-sm">
<h3 className="text-[var(--theme-text)]/60 uppercase tracking-widest text-[14px] mb-4">Total Analyses</h3>
<p className="text-4xl font-bold font-mono tracking-tighter text-[var(--theme-text)]">{stats.summary.total}</p>
</div>
<div className="grid grid-cols-2 gap-6">
<div className="p-6 bg-[var(--theme-text)]/5 border border-[var(--theme-border)] rounded-2xl hover:border-red-500/50 transition backdrop-blur-sm group">
<h3 className="text-[var(--theme-text)]/40 uppercase tracking-widest text-[14px] mb-6.5">Synthetic</h3>
<p className="text-2xl font-bold font-mono text-red-400 group-hover:text-red-300 transition">{stats.summary.ai}%</p>
</div>
<div className="p-6 bg-[var(--theme-text)]/5 border border-[var(--theme-border)] rounded-2xl hover:border-green-500/50 transition backdrop-blur-sm group">
<h3 className="text-[var(--theme-text)]/40 uppercase tracking-widest text-[14px] mb-6.5">Authentic</h3>
<p className="text-2xl font-bold font-mono text-green-400 group-hover:text-green-300 transition">{stats.summary.real}%</p>
</div>
</div>
</div>
{/* Charts Container */}
<div className="lg:col-span-2 grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="p-6 bg-[var(--theme-text)]/5 border border-[var(--theme-border)] rounded-2xl backdrop-blur-sm flex flex-col h-[280px]">
<h3 className="text-[var(--theme-text)]/60 text-sm tracking-widest uppercase mb-4 text-center">Result Distribution</h3>
<div className="flex-1 w-full min-h-0">
<ResponsiveContainer width="100%" height="100%">
<PieChart>
<Pie data={stats.pieData} dataKey="value" cx="50%" cy="50%" innerRadius={60} outerRadius={80} paddingAngle={5} stroke="none">
{stats.pieData.map((e, index) => <Cell key={`cell-${index}`} fill={e.color} />)}
</Pie>
<Tooltip
contentStyle={{ backgroundColor: 'var(--theme-bg)', backdropFilter: 'blur(12px)', borderColor: 'var(--theme-border)', borderRadius: '12px' }}
itemStyle={{ color: 'var(--theme-text)' }}
/>
</PieChart>
</ResponsiveContainer>
</div>
</div>
<div className="p-6 bg-[var(--theme-text)]/5 border border-[var(--theme-border)] rounded-2xl backdrop-blur-sm flex flex-col h-[280px]">
<h3 className="text-[var(--theme-text)]/60 text-sm tracking-widest uppercase mb-4 text-center">Upload Volume</h3>
<div className="flex-1 w-full min-h-0">
<ResponsiveContainer width="100%" height="100%">
<BarChart data={stats.barData} margin={{ top: 10, right: 10, left: -20, bottom: 0 }}>
<XAxis dataKey="date" stroke="var(--theme-text)" opacity={0.5} fontSize={10} tickLine={false} axisLine={false} />
<YAxis stroke="var(--theme-text)" opacity={0.5} fontSize={10} tickLine={false} axisLine={false} allowDecimals={false} />
<BarTooltip
cursor={{fill: 'var(--theme-border)'}}
contentStyle={{ backgroundColor: 'var(--theme-bg)', backdropFilter: 'blur(12px)', borderColor: 'var(--theme-border)', borderRadius: '8px' }}
/>
<Bar dataKey="uploads" fill="var(--theme-text)" radius={[4, 4, 0, 0]} opacity={0.8} />
</BarChart>
</ResponsiveContainer>
</div>
</div>
</div>
</div>
</div>
);
}