Files
ngo-toolkit/app/admin/page.tsx
T
2026-03-18 18:26:24 +08:00

85 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { useUser } from '@auth0/nextjs-auth0/client';
import { useEffect, useState } from 'react';
import Link from 'next/link';
interface Metrics {
total_sessions: number;
paid_sessions: number;
total_leads: number;
total_tokens: number;
by_tool: { tool: string; count: string }[];
}
export default function AdminDashboard() {
const { user, isLoading } = useUser();
const [metrics, setMetrics] = useState<Metrics | null>(null);
useEffect(() => {
if (user) {
fetch('/api/admin/metrics').then((r) => r.json()).then(setMetrics);
}
}, [user]);
if (isLoading) return <div className="p-8 text-center">Loading...</div>;
if (!user) {
return (
<div className="p-8 text-center">
<h1 className="text-2xl font-bold mb-4">Admin Access Required</h1>
<a href="/api/auth/login" className="bg-accent text-white px-6 py-2 rounded-lg">
Sign In
</a>
</div>
);
}
return (
<div className="max-w-6xl mx-auto px-4 py-8">
<div className="flex justify-between items-center mb-8">
<h1 className="text-2xl font-bold">Admin Dashboard</h1>
<div className="flex gap-4">
<Link href="/admin/config" className="text-sm text-accent hover:underline"> Config</Link>
<Link href="/admin/leads" className="text-sm text-accent hover:underline">👥 Leads</Link>
<a href="/api/auth/logout" className="text-sm text-gray-500 hover:underline">Sign Out</a>
</div>
</div>
{metrics && (
<div className="grid md:grid-cols-4 gap-4 mb-8">
<div className="bg-white border rounded-xl p-6">
<div className="text-3xl font-bold text-accent">{metrics.total_sessions}</div>
<div className="text-sm text-gray-500">Total Sessions</div>
</div>
<div className="bg-white border rounded-xl p-6">
<div className="text-3xl font-bold text-green-600">{metrics.paid_sessions}</div>
<div className="text-sm text-gray-500">Paid Sessions</div>
</div>
<div className="bg-white border rounded-xl p-6">
<div className="text-3xl font-bold text-blue-600">{metrics.total_leads}</div>
<div className="text-sm text-gray-500">Leads Captured</div>
</div>
<div className="bg-white border rounded-xl p-6">
<div className="text-3xl font-bold text-purple-600">{metrics.total_tokens.toLocaleString()}</div>
<div className="text-sm text-gray-500">Tokens Used</div>
</div>
</div>
)}
{metrics?.by_tool && (
<div className="bg-white border rounded-xl p-6">
<h2 className="font-semibold mb-4">Usage by Tool</h2>
<div className="space-y-2">
{metrics.by_tool.map((t) => (
<div key={t.tool} className="flex justify-between">
<span className="capitalize">{t.tool.replace(/-/g, ' ')}</span>
<span className="font-mono">{t.count}</span>
</div>
))}
</div>
</div>
)}
</div>
);
}