"use client" import { useEffect, useState } from "react" import Link from "next/link" import { useRouter } from "next/navigation" import { ArrowRight, ShieldCheck } from "lucide-react" type DashboardStats = { total_courses: number total_lessons: number total_modules?: number total_users?: number total_logs?: number active_students: number completion_rate: number } type LogItem = { id: string timestamp: string event_type: string action: string status_code: number ip: string path: string } type ChartPoint = { label: string value: number } type DashboardCharts = { events: ChartPoint[] status_codes: ChartPoint[] methods: ChartPoint[] } const API_BASE = "http://127.0.0.1:5000" export default function AdminDashboardPage() { const router = useRouter() const [ready, setReady] = useState(false) const [stats, setStats] = useState({ total_courses: 0, total_lessons: 0, total_modules: 0, total_users: 0, total_logs: 0, active_students: 0, completion_rate: 0, }) const [recentLogs, setRecentLogs] = useState([]) const [recentActions, setRecentActions] = useState([]) const [alertsCount, setAlertsCount] = useState(0) const [charts, setCharts] = useState({ events: [], status_codes: [], methods: [] }) const getToken = () => localStorage.getItem("admin_token") const headers = () => { const token = getToken() return token ? { "Content-Type": "application/json", Authorization: `Bearer ${token}` } : { "Content-Type": "application/json" } } const verifyAuth = async () => { const token = getToken() if (!token) { router.push("/admin/login") return false } const resp = await fetch(`${API_BASE}/api/admin/test`, { headers: headers() }) if (!resp.ok) { localStorage.removeItem("admin_token") router.push("/admin/login") return false } return true } const fetchDashboardData = async () => { const [statsResp, logsResp, actionsResp, alertsResp, chartsResp] = await Promise.all([ fetch(`${API_BASE}/api/admin/dashboard`, { headers: headers() }), fetch(`${API_BASE}/api/admin/logs?limit=8`, { headers: headers() }), fetch(`${API_BASE}/api/admin/recent-actions?limit=8`, { headers: headers() }), fetch(`${API_BASE}/api/admin/alerts?limit=50`, { headers: headers() }), fetch(`${API_BASE}/api/admin/analytics/activity`, { headers: headers() }), ]) if (statsResp.ok) { const data = await statsResp.json() setStats({ total_courses: Number(data.total_courses || 0), total_lessons: Number(data.total_lessons || 0), total_modules: Number(data.total_modules || 0), total_users: Number(data.total_users || 0), total_logs: Number(data.total_logs || 0), active_students: Number(data.active_students || 0), completion_rate: Number(data.completion_rate || 0), }) } if (logsResp.ok) { const data = await logsResp.json() setRecentLogs(Array.isArray(data.logs) ? data.logs : []) } if (actionsResp.ok) { const data = await actionsResp.json() setRecentActions(Array.isArray(data.actions) ? data.actions : []) } if (alertsResp.ok) { const data = await alertsResp.json() setAlertsCount(Number(data.count || 0)) } if (chartsResp.ok) { const data = await chartsResp.json() if (data.charts) { setCharts({ events: Array.isArray(data.charts.events) ? data.charts.events : [], status_codes: Array.isArray(data.charts.status_codes) ? data.charts.status_codes : [], methods: Array.isArray(data.charts.methods) ? data.charts.methods : [], }) } } } useEffect(() => { const init = async () => { const ok = await verifyAuth() if (!ok) return setReady(true) await fetchDashboardData() } init() }, []) if (!ready) { return (

Loading admin dashboard...

) } return (

Admin Dashboard

Real-time operational metrics sourced from database collections.

Recent Security and Activity Logs

Open Logs
{recentLogs.map((log) => ( ))}
Time Event Action Status
{new Date(log.timestamp).toLocaleString()} {log.event_type} {log.action} = 400 ? "bg-red-100 text-red-700" : "bg-green-100 text-green-700"}`}> {log.status_code}

Quick Actions

Recent Actions

Open Full Logs
{recentActions.map((item) => ( ))}
Time Event Action IP Status
{new Date(item.timestamp).toLocaleString()} {item.event_type} {item.action} {item.ip} {item.status_code}
) } function StatCard({ label, value, color }: { label: string; value: number | string; color: string }) { return (

{label}

{value}

) } function QuickLink({ href, title, subtitle }: { href: string; title: string; subtitle: string }) { return (

{title}

{subtitle}

) } function ChartCard({ title, data }: { title: string; data: ChartPoint[] }) { const max = Math.max(...data.map((x) => x.value), 1) return (

{title}

{data.length === 0 ? (

No data

) : ( data.map((item) => (
{item.label} {item.value}
)) )}
) }