HEX
Server: nginx/1.18.0
System: Linux vcwordpress 5.15.0-174-generic #184-Ubuntu SMP Fri Mar 13 18:41:50 UTC 2026 x86_64
User: root (0)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
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;