"use client" import { Nav } from "@/components/core/nav"; import Altcha from "@/components/core/altcha"; import { authClient } from "@/util/auth-client"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; import { TbShield, TbUsers, TbSend, TbCheck, TbX, TbClock, TbEdit, TbNotes, TbChartLine as TbChart, TbSettings, TbTrendingUp, TbCalendar, TbEye, TbUserMinus, } from "react-icons/tb"; interface ExtendedUser { id: string; name: string; email: string; emailVerified: boolean; createdAt: Date; updatedAt: Date; image?: string | null; role?: string; } interface User { id: string; name: string; email: string; emailVerified: boolean; role: 'user' | 'admin'; createdAt: string; updatedAt: string; } interface ServiceRequest { id: string; userId: string; userName: string; userEmail: string; serviceName: string; serviceDescription: string; reason: string; status: 'pending' | 'approved' | 'denied'; adminNotes?: string; reviewedAt?: string; createdAt: string; updatedAt: string; } interface Service { id: string; name: string; description: string; priceStatus: string; joinLink?: string; enabled: boolean; createdAt: string; updatedAt: string; users: { userId: string; userName: string; userEmail: string; grantedAt: string; }[]; } interface ActivityData { requestActivity: Array<{ date: string; count: number; status: string }>; userActivity: Array<{ date: string; count: number }>; accessActivity: Array<{ date: string; count: number }>; recentActivity: Array<{ id: string; type: string; description: string; status: string; createdAt: string; userName: string; serviceName: string; }>; servicePopularity: Array<{ serviceName: string; requestCount: number; approvedCount: number; }>; totals: { totalRequests: number; totalUsers: number; totalAccess: number; }; period: number; } export default function AdminDashboard() { const router = useRouter(); const { data: session, isPending } = authClient.useSession(); const [mounted, setMounted] = useState(false); const [accessGranted, setAccessGranted] = useState(false); const [users, setUsers] = useState([]); const [requests, setRequests] = useState([]); const [services, setServices] = useState([]); const [activityData, setActivityData] = useState(null); const [loading, setLoading] = useState(true); const [activeTab, setActiveTab] = useState<'overview' | 'users' | 'requests' | 'services'>('overview'); const [editingRequest, setEditingRequest] = useState(null); const [requestStatus, setRequestStatus] = useState<'pending' | 'approved' | 'denied'>('pending'); const [adminNotes, setAdminNotes] = useState(""); const [selectedService, setSelectedService] = useState(""); const [selectedUser, setSelectedUser] = useState(""); const [editingService, setEditingService] = useState(null); const [serviceSettings, setServiceSettings] = useState({ enabled: true, priceStatus: "open" as "open" | "invite-only" | "by-request", description: "", joinLink: "" }); useEffect(() => { setMounted(true); }, []); useEffect(() => { if (mounted && !isPending && !session) { router.push("/login?message=Please sign in to access the admin dashboard"); } }, [session, isPending, mounted, router]); useEffect(() => { if (session && (session.user as ExtendedUser).role !== 'admin') { router.push("/dashboard?message=Access denied: Admin privileges required"); } }, [session, router]); useEffect(() => { if (session && (session.user as ExtendedUser).role === 'admin' && accessGranted) { fetchData(); } }, [session, accessGranted]); useEffect(() => { if (session && (session.user as ExtendedUser).role === 'admin' && accessGranted) { fetchData(); } }, [activeTab, session, accessGranted]); const fetchData = async () => { setLoading(true); try { const [usersResponse, requestsResponse, servicesResponse, activityResponse] = await Promise.all([ fetch("/api/admin/users"), fetch("/api/admin/requests"), fetch("/api/admin/services"), fetch("/api/admin/activity?period=7") ]); if (usersResponse.ok) { const usersData = await usersResponse.json(); setUsers(usersData.users); } if (requestsResponse.ok) { const requestsData = await requestsResponse.json(); setRequests(requestsData.requests); } if (servicesResponse.ok) { const servicesData = await servicesResponse.json(); setServices(servicesData.services); } if (activityResponse.ok) { const activityResponseData = await activityResponse.json(); setActivityData(activityResponseData); } } catch (error) { console.error("Error fetching admin data:", error); } finally { setLoading(false); } }; const handleCaptchaVerification = (token: string) => { if (token) { setAccessGranted(true); } }; const updateUserRole = async (userId: string, newRole: 'user' | 'admin') => { try { const response = await fetch("/api/admin/users", { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ userId, role: newRole }), }); if (response.ok) { setUsers(users.map(user => user.id === userId ? { ...user, role: newRole } : user )); } } catch (error) { console.error("Error updating user role:", error); } }; const updateRequestStatus = async (requestId: string) => { try { const response = await fetch("/api/admin/requests", { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ requestId, status: requestStatus, adminNotes: adminNotes || undefined }), }); if (response.ok) { setRequests(requests.map(request => request.id === requestId ? { ...request, status: requestStatus, adminNotes, reviewedAt: new Date().toISOString() } : request )); setEditingRequest(null); setAdminNotes(""); } } catch (error) { console.error("Error updating request:", error); } }; const grantServiceAccess = async (userId: string, serviceId: string) => { try { const response = await fetch("/api/admin/services", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ action: 'grant', userId, serviceId }), }); if (response.ok) { fetchData(); } } catch (error) { console.error("Error granting service access:", error); } }; const revokeServiceAccess = async (userId: string, serviceId: string) => { try { const response = await fetch("/api/admin/services", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ action: 'revoke', userId, serviceId }), }); if (response.ok) { fetchData(); } } catch (error) { console.error("Error revoking service access:", error); } }; const updateService = async (serviceId: string) => { try { const response = await fetch("/api/admin/services", { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ serviceId, enabled: serviceSettings.enabled, priceStatus: serviceSettings.priceStatus, description: serviceSettings.description, joinLink: serviceSettings.joinLink }), }); if (response.ok) { setEditingService(null); fetchData(); } } catch (error) { console.error("Error updating service:", error); } }; const getStatusIcon = (status: string) => { switch (status) { case 'pending': return ; case 'approved': return ; case 'denied': return ; default: return ; } }; const getStatusColor = (status: string) => { switch (status) { case 'pending': return 'text-yellow-600 bg-yellow-50 border-yellow-200'; case 'approved': return 'text-green-600 bg-green-50 border-green-200'; case 'denied': return 'text-red-600 bg-red-50 border-red-200'; default: return 'text-gray-600 bg-gray-50 border-gray-200'; } }; if (!mounted || isPending) { return (
); } if (!session) { return (
); } if ((session.user as ExtendedUser).role !== 'admin') { return (
); } if (!accessGranted) { return (
); } const pendingRequestsCount = requests.filter(r => r.status === 'pending').length; const totalUsersCount = users.length; const adminUsersCount = users.filter(u => u.role === 'admin').length; return (