File: /var/www/igsms.viitorcloud.co/igsmsportal/views/AnalyticsOverview.tsx
import React, { useMemo } from 'react';
import { Grievance, GrievanceStatus } from '../types';
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, PieChart, Pie, Cell, LineChart, Line } from 'recharts';
interface AnalyticsOverviewProps {
activeTab: string;
grievances: Grievance[];
}
const AnalyticsOverview: React.FC<AnalyticsOverviewProps> = ({ activeTab, grievances }) => {
const COLORS = ['#10B981', '#F59E0B', '#3B82F6', '#EF4444'];
const stats = useMemo(() => {
const total = grievances.length;
const resolved = grievances.filter(g => g.status === GrievanceStatus.RESOLVED).length;
const pending = grievances.filter(g => g.status === GrievanceStatus.PENDING).length;
const escalated = grievances.filter(g => g.status === GrievanceStatus.ESCALATED).length;
return [
{ label: 'Total Volume', value: total, delta: '+5%', color: 'blue' },
{ label: 'Resolved', value: resolved, delta: '+12%', color: 'green' },
{ label: 'Pending', value: pending, delta: '-3%', color: 'orange' },
{ label: 'Escalated', value: escalated, delta: '+2%', color: 'red' },
];
}, [grievances]);
const pieData = useMemo(() => [
{ name: 'Resolved', value: grievances.filter(g => g.status === GrievanceStatus.RESOLVED).length },
{ name: 'Pending', value: grievances.filter(g => g.status === GrievanceStatus.PENDING).length },
{ name: 'In Progress', value: grievances.filter(g => g.status === GrievanceStatus.IN_PROGRESS).length },
{ name: 'Escalated', value: grievances.filter(g => g.status === GrievanceStatus.ESCALATED).length },
], [grievances]);
const deptData = useMemo(() => {
const depts: Record<string, { name: string, resolved: number, pending: number, total: number }> = {};
grievances.forEach(g => {
const dept = g.department || 'General';
if (!depts[dept]) depts[dept] = { name: dept.split(' ')[0], resolved: 0, pending: 0, total: 0 };
if (g.status === GrievanceStatus.RESOLVED) depts[dept].resolved++;
else depts[dept].pending++;
depts[dept].total++;
});
return Object.values(depts);
}, [grievances]);
const districtData = useMemo(() => {
const districts: Record<string, { name: string, performance: number }> = {};
grievances.forEach(g => {
if (!districts[g.district]) districts[g.district] = { name: g.district, performance: 0 };
if (g.status === GrievanceStatus.RESOLVED) districts[g.district].performance += 20;
else districts[g.district].performance += 5;
});
return Object.values(districts);
}, [grievances]);
const StatusLegend = () => (
<div className="flex flex-wrap items-center gap-6 px-8 py-4 bg-white/50 backdrop-blur rounded-[2rem] border border-slate-200/50 shadow-sm mb-6">
<div className="flex items-center gap-2">
<div className="w-3 h-3 rounded-full bg-[#10B981]"></div>
<span className="text-[10px] font-black text-slate-600 uppercase tracking-widest">Resolved</span>
</div>
<div className="flex items-center gap-2">
<div className="w-3 h-3 rounded-full bg-[#F59E0B]"></div>
<span className="text-[10px] font-black text-slate-600 uppercase tracking-widest">Pending</span>
</div>
<div className="flex items-center gap-2">
<div className="w-3 h-3 rounded-full bg-[#3B82F6]"></div>
<span className="text-[10px] font-black text-slate-600 uppercase tracking-widest">In Progress</span>
</div>
<div className="flex items-center gap-2">
<div className="w-3 h-3 rounded-full bg-[#EF4444]"></div>
<span className="text-[10px] font-black text-slate-600 uppercase tracking-widest">Escalated</span>
</div>
</div>
);
const renderDashboard = () => (
<div className="space-y-8 animate-fade-in">
<StatusLegend />
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
{stats.map((stat, i) => (
<div key={i} className="bg-white p-6 rounded-3xl border border-slate-100 shadow-sm group hover:border-blue-200 transition-colors">
<p className="text-[10px] font-black text-slate-400 uppercase tracking-widest">{stat.label}</p>
<p className="text-3xl font-black text-slate-900 mt-2">{stat.value}</p>
<div className={`mt-3 text-[10px] font-black uppercase ${stat.delta.startsWith('+') ? 'text-emerald-500' : 'text-rose-500'}`}>
{stat.delta} trend
</div>
</div>
))}
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="lg:col-span-1 bg-white p-8 rounded-[2.5rem] border border-slate-100 shadow-sm min-h-[450px] flex flex-col">
<div className="flex justify-between items-center mb-6">
<h3 className="font-black text-slate-900 uppercase text-xs tracking-widest">Status Mix</h3>
<i className="fa-solid fa-chart-pie text-slate-200 text-lg"></i>
</div>
<div className="flex-1">
<ResponsiveContainer width="100%" height="100%">
<PieChart>
<Pie data={pieData} cx="50%" cy="50%" innerRadius={60} outerRadius={80} paddingAngle={10} dataKey="value" stroke="none">
{pieData.map((_, index) => <Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />)}
</Pie>
<Tooltip contentStyle={{ borderRadius: '16px', border: 'none', boxShadow: '0 10px 15px -3px rgb(0 0 0 / 0.1)', fontSize: '10px', fontWeight: 'bold' }} />
</PieChart>
</ResponsiveContainer>
</div>
{/* In-Card Legend below Status Mix */}
<div className="grid grid-cols-2 gap-y-3 mt-6 pt-6 border-t border-slate-50">
<div className="flex items-center gap-2">
<div className="w-2.5 h-2.5 rounded-full bg-[#10B981]"></div>
<span className="text-[10px] font-black text-slate-500 uppercase tracking-wider">Resolved</span>
</div>
<div className="flex items-center gap-2">
<div className="w-2.5 h-2.5 rounded-full bg-[#F59E0B]"></div>
<span className="text-[10px] font-black text-slate-500 uppercase tracking-wider">Pending</span>
</div>
<div className="flex items-center gap-2">
<div className="w-2.5 h-2.5 rounded-full bg-[#3B82F6]"></div>
<span className="text-[10px] font-black text-slate-500 uppercase tracking-wider">In Progress</span>
</div>
<div className="flex items-center gap-2">
<div className="w-2.5 h-2.5 rounded-full bg-[#EF4444]"></div>
<span className="text-[10px] font-black text-slate-500 uppercase tracking-wider">Escalated</span>
</div>
</div>
</div>
<div className="lg:col-span-2 bg-white p-8 rounded-[2.5rem] border border-slate-100 shadow-sm h-[450px]">
<div className="flex justify-between items-center mb-6">
<h3 className="font-black text-slate-900 uppercase text-xs tracking-widest">Department Throughput</h3>
<i className="fa-solid fa-chart-simple text-slate-200 text-lg"></i>
</div>
<ResponsiveContainer width="100%" height="85%">
<BarChart data={deptData}>
<XAxis dataKey="name" axisLine={false} tickLine={false} tick={{ fontSize: 10, fill: '#94a3b8', fontWeight: 800 }} />
<YAxis axisLine={false} tickLine={false} tick={{ fontSize: 10, fill: '#94a3b8' }} />
<Tooltip cursor={{ fill: '#f8fafc' }} contentStyle={{ borderRadius: '16px', border: 'none', boxShadow: '0 10px 15px -3px rgb(0 0 0 / 0.1)', fontSize: '10px', fontWeight: 'bold' }} />
<Bar dataKey="resolved" fill="#10B981" radius={[4, 4, 0, 0]} barSize={20} />
<Bar dataKey="pending" fill="#F59E0B" radius={[4, 4, 0, 0]} barSize={20} />
</BarChart>
</ResponsiveContainer>
</div>
</div>
</div>
);
const renderDepts = () => (
<div className="space-y-8 animate-fade-in">
<StatusLegend />
<div className="bg-white p-10 rounded-[2.5rem] border border-slate-100 shadow-sm">
<h3 className="text-xl font-black text-slate-900 mb-8">Departmental Efficiency Ranking</h3>
<div className="space-y-6">
{deptData.map((d, i) => (
<div key={i} className="flex items-center justify-between p-6 bg-slate-50 rounded-2xl border border-slate-100">
<div className="flex items-center gap-4">
<div className="w-10 h-10 bg-white rounded-xl flex items-center justify-center font-black text-blue-600 shadow-sm border border-slate-200">
{i + 1}
</div>
<div>
<p className="font-black text-slate-900">{d.name} Dept</p>
<p className="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{d.total} Total Requests</p>
</div>
</div>
<div className="flex gap-10">
<div className="text-center">
<p className="text-[10px] font-black text-emerald-500 uppercase tracking-widest">Resolved</p>
<p className="text-lg font-black text-slate-900">{d.resolved}</p>
</div>
<div className="text-center">
<p className="text-[10px] font-black text-amber-500 uppercase tracking-widest">Active</p>
<p className="text-lg font-black text-slate-900">{d.pending}</p>
</div>
</div>
</div>
))}
</div>
</div>
</div>
);
const renderRanking = () => (
<div className="space-y-8 animate-fade-in">
<div className="bg-white p-10 rounded-[2.5rem] border border-slate-100 shadow-sm">
<h3 className="text-xl font-black text-slate-900 mb-8">District Performance Meter</h3>
<div className="h-[400px]">
<ResponsiveContainer width="100%" height="100%">
<BarChart data={districtData} layout="vertical">
<XAxis type="number" hide />
<YAxis dataKey="name" type="category" axisLine={false} tickLine={false} tick={{ fontSize: 10, fill: '#64748b', fontWeight: 800 }} width={100} />
<Tooltip contentStyle={{ borderRadius: '16px', border: 'none', fontSize: '10px', fontWeight: 'bold' }} />
<Bar dataKey="performance" fill="#3B82F6" radius={[0, 8, 8, 0]} barSize={24} />
</BarChart>
</ResponsiveContainer>
</div>
</div>
</div>
);
const renderReports = () => (
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 animate-fade-in">
<div className="bg-gradient-to-br from-slate-900 to-slate-800 p-10 rounded-[3rem] text-white shadow-xl relative overflow-hidden group">
<div className="relative z-10">
<h3 className="text-2xl font-black mb-4">AI Executive Summary</h3>
<p className="text-slate-400 text-sm leading-relaxed mb-8">Based on last 30 days data, the state has seen a <span className="text-emerald-400 font-bold">14% improvement</span> in resolution speed in the Urban Development sector.</p>
<div className="space-y-4">
{['Revenue Dept needs resource allocation in Surat', 'Health infrastructure grievances peaked in Rajkot', 'Education scholarship queries resolved in record time'].map((insight, idx) => (
<div key={idx} className="flex gap-3 items-start p-4 bg-white/5 rounded-2xl border border-white/10">
<i className="fa-solid fa-sparkles text-blue-400 mt-1"></i>
<p className="text-xs font-bold text-slate-300">{insight}</p>
</div>
))}
</div>
</div>
</div>
<div className="bg-white p-10 rounded-[3rem] border border-slate-100 shadow-sm flex flex-col">
<h3 className="text-xl font-black text-slate-900 mb-6">Historical Forecast</h3>
<div className="flex-1">
<ResponsiveContainer width="100%" height="100%">
<LineChart data={districtData}>
<CartesianGrid strokeDasharray="3 3" stroke="#f1f5f9" vertical={false} />
<XAxis dataKey="name" hide />
<YAxis hide />
<Tooltip />
<Line type="monotone" dataKey="performance" stroke="#3B82F6" strokeWidth={4} dot={{ r: 6, fill: '#3B82F6', strokeWidth: 2, stroke: '#fff' }} />
</LineChart>
</ResponsiveContainer>
</div>
<div className="mt-8 p-6 bg-blue-50 rounded-2xl border border-blue-100">
<p className="text-xs font-black text-blue-800 uppercase tracking-widest mb-1">Prediction</p>
<p className="text-sm font-bold text-blue-900">Estimated resolution volume for next week: <span className="text-xl font-black">1,420</span></p>
</div>
</div>
</div>
);
return (
<div className="space-y-10 py-4">
<header className="flex justify-between items-center">
<div>
<h2 className="text-3xl font-black text-slate-900 tracking-tight">
{activeTab === 'dashboard' ? 'State Live Insights' :
activeTab === 'dept-wise' ? 'Department Performance' :
activeTab === 'ranking' ? 'District Rankings' : 'Intelligence Center'}
</h2>
<p className="text-slate-500 font-medium">Gujarat Integrated Governance & Monitoring Hub</p>
</div>
<div className="flex gap-4">
<button className="bg-white border border-slate-200 px-6 py-3 rounded-2xl text-[10px] font-black text-slate-500 hover:text-slate-900 transition-all uppercase tracking-widest shadow-sm">
<i className="fa-solid fa-calendar mr-2"></i> Last 30 Days
</button>
<button className="bg-blue-600 text-white px-6 py-3 rounded-2xl text-[10px] font-black hover:bg-blue-700 transition-all uppercase tracking-widest shadow-lg shadow-blue-500/20">
<i className="fa-solid fa-download mr-2"></i> Generate PDF
</button>
</div>
</header>
{activeTab === 'dashboard' && renderDashboard()}
{activeTab === 'dept-wise' && renderDepts()}
{activeTab === 'ranking' && renderRanking()}
{activeTab === 'reports' && renderReports()}
</div>
);
};
export default AnalyticsOverview;