import { useState, useEffect } from 'react'
import type { NextPage } from 'next'
import Head from 'next/head'
import AdminLayout from '../../components/AdminLayout'
import {
ChartBarIcon,
ShieldExclamationIcon,
DocumentTextIcon,
ExclamationTriangleIcon,
ClockIcon,
EyeIcon,
ServerStackIcon,
CircleStackIcon,
UserGroupIcon,
GlobeAltIcon,
ArrowTrendingUpIcon,
ArrowTrendingDownIcon,
CheckCircleIcon
} from '@heroicons/react/24/outline'
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
BarElement,
Title,
Tooltip,
Legend,
ArcElement,
} from 'chart.js'
import { Line, Bar, Doughnut } from 'react-chartjs-2'
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
BarElement,
Title,
Tooltip,
Legend,
ArcElement
)
interface DashboardStats {
// Basic stats
total_sources: number
pending_sources: number
pending_reports: number
high_risk_sources: number
sources_added_week: number
reports_today: number
// Advanced stats
verified_sources_today: number
api_calls_today: number
unique_visitors_today: number
system_uptime: string
database_size: string
active_moderators: number
// Performance metrics
avg_response_time: number
api_success_rate: number
memory_usage: number
cpu_usage: number
// Trend data
sources_trend: Array<{date: string, count: number}>
reports_trend: Array<{date: string, count: number}>
risk_distribution: Array<{level: string, count: number}>
category_distribution: Array<{category: string, count: number}>
// Recent activities
recent_sources: Array<{
id: number
url: string
status: string
created_at: string
}>
recent_reports: Array<{
id: number
source_url: string
status: string
created_at: string
}>
}
const StatCard = ({ title, value, change, icon: Icon, trend, color = 'blue' }: {
title: string
value: string | number
change?: number
icon: any
trend?: 'up' | 'down' | 'neutral'
color?: 'blue' | 'green' | 'red' | 'yellow' | 'purple'
}) => {
const colorClasses = {
blue: 'bg-blue-500',
green: 'bg-green-500',
red: 'bg-red-500',
yellow: 'bg-yellow-500',
purple: 'bg-purple-500'
}
return (
- {title}
-
{typeof value === 'number' ? value.toLocaleString() : value}
{change !== undefined && (
0 ? 'text-green-600' : change < 0 ? 'text-red-600' : 'text-gray-500'
}`}>
{change > 0 ? (
) : change < 0 ? (
) : null}
{Math.abs(change)}%
)}
)
}
const AdminDashboard: NextPage = () => {
const [stats, setStats] = useState(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
fetchStats()
const interval = setInterval(fetchStats, 30000) // Refresh every 30 seconds
return () => clearInterval(interval)
}, [])
const fetchStats = async () => {
try {
const response = await fetch('/api/admin/dashboard')
if (response.ok) {
const data = await response.json()
setStats(data)
}
} catch (error) {
console.error('Failed to fetch stats:', error)
} finally {
setLoading(false)
}
}
// Chart configurations
const sourcesChartData = {
labels: stats?.sources_trend?.map(item => new Date(item.date).toLocaleDateString('sk-SK')) || [],
datasets: [
{
label: 'Nové zdroje',
data: stats?.sources_trend?.map(item => item.count) || [],
borderColor: 'rgb(59, 130, 246)',
backgroundColor: 'rgba(59, 130, 246, 0.1)',
tension: 0.4,
},
],
}
const reportsChartData = {
labels: stats?.reports_trend?.map(item => new Date(item.date).toLocaleDateString('sk-SK')) || [],
datasets: [
{
label: 'Nové hlásenia',
data: stats?.reports_trend?.map(item => item.count) || [],
backgroundColor: 'rgba(34, 197, 94, 0.8)',
borderColor: 'rgb(34, 197, 94)',
borderWidth: 1,
},
],
}
const riskDistributionData = {
labels: stats?.risk_distribution?.map(item => `Úroveň ${item.level}`) || [],
datasets: [
{
data: stats?.risk_distribution?.map(item => item.count) || [],
backgroundColor: [
'#ef4444', // red
'#f97316', // orange
'#eab308', // yellow
'#22c55e', // green
'#3b82f6', // blue
],
borderWidth: 2,
borderColor: '#ffffff',
},
],
}
if (loading) {
return (
Dashboard - Hliadka.sk Admin
)
}
return (
Dashboard - Hliadka.sk Admin
{/* Key Metrics */}
{/* System Performance Metrics */}
{/* Charts Section */}
{/* Sources Trend */}
Trend pridávania zdrojov
{/* Reports Trend */}
Trend hlásení
{/* Risk Distribution and Category Stats */}
Distribúcia rizika
Systémové informácie
- Uptime systému
- {stats?.system_uptime || 'N/A'}
- Veľkosť databázy
- {stats?.database_size || 'N/A'}
- Priemerný response time
- {stats?.avg_response_time || 0}ms
- Využitie pamäte
- {stats?.memory_usage || 0}%
- Jedinečných návštevníkov dnes
- {stats?.unique_visitors_today || 0}
- Overených zdrojov dnes
- {stats?.verified_sources_today || 0}
{/* Recent Activity */}
Najnovšie zdroje
{stats?.recent_sources?.map((source, idx) => (
-
{idx !== (stats.recent_sources?.length || 0) - 1 && (
)}
{new Date(source.created_at).toLocaleString('sk-SK')}
)) || (
-
Žiadne nedávne aktivity
)}
Najnovšie hlásenia
{stats?.recent_reports?.map((report, idx) => (
-
{idx !== (stats.recent_reports?.length || 0) - 1 && (
)}
{new Date(report.created_at).toLocaleString('sk-SK')}
)) || (
-
Žiadne nedávne hlásenia
)}
)
}
export default AdminDashboard