"use client"; import { useEffect, useMemo, useState } from "react"; import Link from "next/link"; import Navbar from "@/components/Navbar"; import Footer from "@/components/Footer"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { toast } from "@/components/ui/toaster"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; type RequestStatus = "pending" | "in_progress" | "completed"; type DistillationRequest = { id: string; sourceDataset: string; studentModel: string; submitterName?: string; additionalNotes: string; upvotes: number; createdAt: string; status: RequestStatus; }; type DatasetRequest = { id: string; sourceModel: string; submitterName?: string; datasetSize: string; reasoningDepth: string; topics: string[]; additionalNotes: string; upvotes: number; createdAt: string; status: RequestStatus; }; const STATUS_OPTIONS: RequestStatus[] = ["pending", "in_progress", "completed"]; function StatusBadge({ status }: { status: RequestStatus }) { if (status === "completed") return Completed; if (status === "in_progress") return In Progress; return Pending; } export default function AdminPage() { const [checking, setChecking] = useState(true); const [admin, setAdmin] = useState(false); const [password, setPassword] = useState(""); const [loginLoading, setLoginLoading] = useState(false); const [distillationRequests, setDistillationRequests] = useState([]); const [datasetRequests, setDatasetRequests] = useState([]); const [loading, setLoading] = useState(false); const [replyOpen, setReplyOpen] = useState>({}); const [replyBody, setReplyBody] = useState>({}); const [replySubmitting, setReplySubmitting] = useState>({}); const allRequests = useMemo(() => { const dist = distillationRequests.map((r) => ({ type: "distillation" as const, request: r })); const data = datasetRequests.map((r) => ({ type: "dataset" as const, request: r })); return [...dist, ...data].sort((a, b) => b.request.upvotes - a.request.upvotes); }, [distillationRequests, datasetRequests]); useEffect(() => { checkAdmin(); }, []); useEffect(() => { if (admin) { fetchAll(); } }, [admin]); async function checkAdmin() { setChecking(true); try { const res = await fetch("/api/admin/me", { cache: "no-store" }); const data = await res.json(); setAdmin(Boolean(data?.admin)); } catch { setAdmin(false); } finally { setChecking(false); } } async function fetchAll() { setLoading(true); try { const [distillRes, datasetRes] = await Promise.all([ fetch("/api/distillation", { cache: "no-store" }), fetch("/api/dataset", { cache: "no-store" }), ]); const [distillData, datasetData] = await Promise.all([distillRes.json(), datasetRes.json()]); setDistillationRequests(Array.isArray(distillData) ? distillData : []); setDatasetRequests(Array.isArray(datasetData) ? datasetData : []); } catch (error) { console.error(error); toast({ title: "Error", description: "Failed to fetch requests", variant: "destructive" }); } finally { setLoading(false); } } async function login() { setLoginLoading(true); try { const res = await fetch("/api/admin/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ password }), }); const data = await res.json(); if (!res.ok) { toast({ title: "Login failed", description: data?.error || "Invalid password", variant: "destructive" }); return; } toast({ title: "Logged in", description: "Admin session started" }); setPassword(""); await checkAdmin(); } catch (error) { console.error(error); toast({ title: "Login failed", description: "Unexpected error", variant: "destructive" }); } finally { setLoginLoading(false); } } async function logout() { try { await fetch("/api/admin/logout", { method: "POST" }); setAdmin(false); toast({ title: "Logged out" }); } catch { toast({ title: "Error", description: "Failed to logout", variant: "destructive" }); } } async function updateStatus(type: "distillation" | "dataset", id: string, status: RequestStatus) { try { const res = await fetch(`/api/admin/requests/${type}/${id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ status }), }); const data = await res.json(); if (!res.ok) { toast({ title: "Error", description: data?.error || "Failed to update status", variant: "destructive" }); return; } toast({ title: "Updated", description: "Status updated" }); await fetchAll(); } catch { toast({ title: "Error", description: "Failed to update status", variant: "destructive" }); } } async function removeRequest(type: "distillation" | "dataset", id: string) { try { const res = await fetch(`/api/admin/requests/${type}/${id}`, { method: "DELETE" }); const data = await res.json(); if (!res.ok) { toast({ title: "Error", description: data?.error || "Failed to delete", variant: "destructive" }); return; } toast({ title: "Deleted", description: "Request removed" }); await fetchAll(); } catch { toast({ title: "Error", description: "Failed to delete", variant: "destructive" }); } } async function submitReply(type: "distillation" | "dataset", id: string) { const key = `${type}:${id}`; const body = (replyBody[key] || "").trim(); if (!body) { toast({ title: "Error", description: "Reply cannot be empty", variant: "destructive" }); return; } setReplySubmitting((prev) => ({ ...prev, [key]: true })); try { const res = await fetch(`/api/admin/requests/${type}/${id}/comments`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ body }), }); const data = await res.json(); if (!res.ok) { toast({ title: "Error", description: data?.error || "Failed to reply", variant: "destructive" }); return; } toast({ title: "Replied", description: "Comment posted" }); setReplyBody((prev) => ({ ...prev, [key]: "" })); setReplyOpen((prev) => ({ ...prev, [key]: false })); } catch { toast({ title: "Error", description: "Failed to reply", variant: "destructive" }); } finally { setReplySubmitting((prev) => ({ ...prev, [key]: false })); } } return (

Admin

Manage requests, update status, and reply.

{admin && ( )}
{checking ? ( Checking session… ) : !admin ? ( Admin Login Password is set via ADMIN_PASSWORD
setPassword(e.target.value)} />
) : (
Total: {allRequests.length}
{allRequests.length === 0 ? ( No requests yet. ) : (
{allRequests.map(({ type, request }) => { const key = `${type}:${request.id}`; const isReplyOpen = Boolean(replyOpen[key]); const title = type === "distillation" ? `${(request as DistillationRequest).sourceDataset} → ${(request as DistillationRequest).studentModel}` : `${(request as DatasetRequest).sourceModel} Dataset (${(request as DatasetRequest).datasetSize})`; return (

{title}

{type} {request.upvotes} upvotes
{request.additionalNotes ? (

{request.additionalNotes}

) : null} {(request as any).submitterName ? (

By {(request as any).submitterName}

) : null} {type === "dataset" ? (
{(request as DatasetRequest).reasoningDepth} reasoning {(request as DatasetRequest).topics?.slice(0, 6)?.map((t) => ( {t} ))}
) : null}
{isReplyOpen && (