203 lines
8.0 KiB
TypeScript
Raw Normal View History

2025-08-15 23:03:15 +07:00
"use client"
import { useState, useEffect } from "react"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Users, Vote, BarChart3, LogOut, Calendar, Settings } from "lucide-react"
import Link from "next/link"
import { AuthGuard } from "@/components/auth-guard"
import { useAuth } from "@/hooks/use-auth"
import apiClient from "@/lib/api-client"
import { API_CONFIG } from "@/lib/config"
function AdminPageContent() {
const { user, logout } = useAuth()
const [stats, setStats] = useState({
totalEvents: 0,
activeEvents: 0,
totalCandidates: 0
})
const [loading, setLoading] = useState(true)
useEffect(() => {
fetchStats()
}, [])
const fetchStats = async () => {
try {
const response = await apiClient.get(API_CONFIG.ENDPOINTS.VOTE_EVENTS)
if (response.data.success) {
const events = response.data.data.vote_events || []
const now = new Date()
const activeEvents = events.filter((event: any) => {
const start = new Date(event.start_date)
const end = new Date(event.end_date)
return now >= start && now <= end
})
const totalCandidates = events.reduce((total: number, event: any) => {
return total + (event.candidates?.length || 0)
}, 0)
setStats({
totalEvents: events.length,
activeEvents: activeEvents.length,
totalCandidates
})
}
} catch (error) {
console.error('Error fetching stats:', error)
} finally {
setLoading(false)
}
}
return (
<div className="min-h-screen bg-gray-50">
<header className="bg-white shadow-sm border-b">
<div className="container mx-auto px-4 py-4 flex justify-between items-center">
<div className="flex items-center gap-4">
<img src="/images/meti-logo.png" alt="METI - New & Renewable Energy" className="h-12 w-auto" />
<h1 className="text-2xl font-bold text-gray-900">Admin Dashboard METI</h1>
</div>
<div className="flex items-center gap-4">
<span className="text-sm text-gray-600">Welcome, {user?.username || 'Admin'}</span>
<Button variant="outline" size="sm" onClick={logout}>
<LogOut className="h-4 w-4 mr-2" />
Logout
</Button>
</div>
</div>
</header>
<div className="container mx-auto px-4 py-8">
{/* Statistics Cards */}
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Total Events</CardTitle>
<Vote className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{loading ? '...' : stats.totalEvents}</div>
<p className="text-xs text-muted-foreground">Vote events created</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Active Events</CardTitle>
<BarChart3 className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{loading ? '...' : stats.activeEvents}</div>
<p className="text-xs text-muted-foreground">Currently running</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Total Candidates</CardTitle>
<Users className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{loading ? '...' : stats.totalCandidates}</div>
<p className="text-xs text-muted-foreground">Across all events</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">System Status</CardTitle>
<Settings className="h-4 w-4 text-green-600" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-green-600">Online</div>
<p className="text-xs text-muted-foreground">All systems operational</p>
</CardContent>
</Card>
</div>
{/* Quick Actions */}
<div className="mb-8">
<h2 className="text-2xl font-bold text-gray-900 mb-6">Quick Actions</h2>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
<Card className="hover:shadow-lg transition-shadow cursor-pointer group">
<CardHeader>
<div className="flex items-center gap-3">
<div className="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center group-hover:bg-blue-200 transition-colors">
<Calendar className="h-6 w-6 text-blue-600" />
</div>
<div>
<CardTitle className="text-lg">Manage Events</CardTitle>
<CardDescription>Create and manage voting events</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<Link href="/admin/events">
<Button className="w-full bg-blue-600 hover:bg-blue-700">
<Settings className="h-4 w-4 mr-2" />
Event Management
</Button>
</Link>
</CardContent>
</Card>
<Card className="hover:shadow-lg transition-shadow cursor-pointer group">
<CardHeader>
<div className="flex items-center gap-3">
<div className="w-12 h-12 bg-green-100 rounded-lg flex items-center justify-center group-hover:bg-green-200 transition-colors">
<Users className="h-6 w-6 text-green-600" />
</div>
<div>
<CardTitle className="text-lg">Manage Members</CardTitle>
<CardDescription>Verify and manage members</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<Link href="/admin/members">
<Button className="w-full bg-green-600 hover:bg-green-700">
<Users className="h-4 w-4 mr-2" />
Member Management
</Button>
</Link>
</CardContent>
</Card>
<Card className="hover:shadow-lg transition-shadow cursor-pointer group">
<CardHeader>
<div className="flex items-center gap-3">
<div className="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center group-hover:bg-purple-200 transition-colors">
<BarChart3 className="h-6 w-6 text-purple-600" />
</div>
<div>
<CardTitle className="text-lg">View Results</CardTitle>
<CardDescription>Monitor voting results</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<Link href="/results">
<Button className="w-full bg-purple-600 hover:bg-purple-700">
<BarChart3 className="h-4 w-4 mr-2" />
View Results
</Button>
</Link>
</CardContent>
</Card>
</div>
</div>
</div>
</div>
)
}
export default function AdminPage() {
return (
<AuthGuard requiredRole="superadmin">
<AdminPageContent />
</AuthGuard>
)
}