File size: 7,413 Bytes
e67ec6b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
"use client";
import { useState, useEffect } from 'react';
import { Users, FileAudio, Activity, ShieldCheck, Crown, Clock } from 'lucide-react';
import { useAuth } from '@clerk/nextjs';
import { useRouter } from 'next/navigation';

export default function AdminDashboard() {
  const [stats, setStats] = useState<any>(null);
  const [loading, setLoading] = useState(true);
  const { isLoaded, isSignedIn } = useAuth();
  const router = useRouter();

  useEffect(() => {
    if (isLoaded && !isSignedIn) {
      router.push("/");
      return;
    }
    
    // Fetch stats
    const baseUrl = process.env.NEXT_PUBLIC_BACKEND_URL || "http://localhost:8000";
    fetch(`${baseUrl}/api/admin/analytics`)
      .then(res => res.json())
      .then(data => {
        setStats(data);
        setLoading(false);
      })
      .catch(err => {
        console.error("Failed to load admin stats", err);
        setLoading(false);
      });
  }, [isLoaded, isSignedIn, router]);

  if (loading) {
    return (
      <div className="min-h-screen flex items-center justify-center pt-20">
        <div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-[#1877F2]"></div>
      </div>
    );
  }

  if (!stats) return <div className="p-20 text-center">Failed to load analytics</div>;

  return (
    <div className="min-h-screen pt-24 pb-20 px-4">
      <div className="max-w-7xl mx-auto">
        <div className="flex items-center justify-between mb-8">
          <h1 className="text-3xl font-bold text-white flex items-center gap-3">
            <ShieldCheck className="w-8 h-8 text-[#1877F2]" /> Platform Admin
          </h1>
          <div className="bg-[#1877F2]/20 text-[#1877F2] px-4 py-1.5 rounded-full text-sm font-bold border border-[#1877F2]/30">
            Live Analytics
          </div>
        </div>

        {/* Top Stats Row */}
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
          <div className="bg-[#111] border border-[#27272a] rounded-2xl p-6">
            <div className="flex items-center gap-4 mb-4">
              <div className="bg-blue-500/20 p-3 rounded-xl"><FileAudio className="w-6 h-6 text-blue-500" /></div>
              <h3 className="text-gray-400 font-medium">Total Extractions</h3>
            </div>
            <div className="text-4xl font-black text-white">{stats.total_tasks}</div>
          </div>
          
          <div className="bg-[#111] border border-[#27272a] rounded-2xl p-6">
            <div className="flex items-center gap-4 mb-4">
              <div className="bg-emerald-500/20 p-3 rounded-xl"><Activity className="w-6 h-6 text-emerald-500" /></div>
              <h3 className="text-gray-400 font-medium">Completed</h3>
            </div>
            <div className="text-4xl font-black text-white">{stats.status_counts?.completed || 0}</div>
          </div>

          <div className="bg-[#111] border border-[#27272a] rounded-2xl p-6">
            <div className="flex items-center gap-4 mb-4">
              <div className="bg-purple-500/20 p-3 rounded-xl"><Users className="w-6 h-6 text-purple-500" /></div>
              <h3 className="text-gray-400 font-medium">Total Users</h3>
            </div>
            <div className="text-4xl font-black text-white">{stats.total_users}</div>
          </div>

          <div className="bg-[#111] border border-[#27272a] rounded-2xl p-6 relative overflow-hidden">
            <div className="absolute top-0 right-0 w-32 h-32 bg-yellow-500/10 rounded-full blur-3xl" />
            <div className="flex items-center gap-4 mb-4 relative z-10">
              <div className="bg-yellow-500/20 p-3 rounded-xl"><Crown className="w-6 h-6 text-yellow-500" /></div>
              <h3 className="text-gray-400 font-medium">Pro Subscribers</h3>
            </div>
            <div className="text-4xl font-black text-white relative z-10">{stats.premium_users}</div>
          </div>
        </div>

        {/* Detailed Breakdown */}
        <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
          <div className="lg:col-span-1 bg-[#111] border border-[#27272a] rounded-2xl p-6">
            <h2 className="text-xl font-bold text-white mb-6">Task Status Breakdown</h2>
            <div className="space-y-4">
              {Object.entries(stats.status_counts || {}).map(([status, count]: [string, any]) => (
                <div key={status} className="flex items-center justify-between bg-black/40 p-4 rounded-xl border border-white/5">
                  <span className="text-gray-300 capitalize flex items-center gap-2">
                    <div className={`w-2 h-2 rounded-full ${
                      status === 'completed' ? 'bg-emerald-500' :
                      status === 'processing' ? 'bg-blue-500' :
                      status === 'failed' ? 'bg-rose-500' : 'bg-gray-500'
                    }`} />
                    {status}
                  </span>
                  <span className="font-bold text-white">{count}</span>
                </div>
              ))}
            </div>
          </div>

          <div className="lg:col-span-2 bg-[#111] border border-[#27272a] rounded-2xl p-6">
            <h2 className="text-xl font-bold text-white mb-6">Recent Activity</h2>
            <div className="overflow-x-auto">
              <table className="w-full text-left border-collapse">
                <thead>
                  <tr className="border-b border-[#27272a] text-gray-400 text-sm">
                    <th className="pb-3 font-medium">Task ID</th>
                    <th className="pb-3 font-medium">User Email</th>
                    <th className="pb-3 font-medium">Status</th>
                    <th className="pb-3 font-medium">Created At</th>
                  </tr>
                </thead>
                <tbody className="divide-y divide-[#27272a]">
                  {stats.recent_tasks?.map((task: any) => (
                    <tr key={task.task_id} className="text-sm">
                      <td className="py-4 font-mono text-gray-400 truncate max-w-[150px]">{task.task_id}</td>
                      <td className="py-4 text-gray-300">{task.user_email || "Anonymous"}</td>
                      <td className="py-4">
                        <span className={`px-2 py-1 rounded text-xs font-bold ${
                          task.status === 'completed' ? 'bg-emerald-500/20 text-emerald-500' :
                          task.status === 'processing' ? 'bg-blue-500/20 text-blue-500' :
                          task.status === 'failed' ? 'bg-rose-500/20 text-rose-500' : 'bg-gray-500/20 text-gray-300'
                        }`}>
                          {task.status.toUpperCase()}
                        </span>
                      </td>
                      <td className="py-4 text-gray-500 flex items-center gap-2">
                        <Clock className="w-3 h-3" />
                        {new Date(task.created_at * 1000).toLocaleString()}
                      </td>
                    </tr>
                  ))}
                  {stats.recent_tasks?.length === 0 && (
                    <tr>
                      <td colSpan={4} className="py-8 text-center text-gray-500">No recent tasks found.</td>
                    </tr>
                  )}
                </tbody>
              </table>
            </div>
          </div>
        </div>

      </div>
    </div>
  );
}