"use client"; import { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import { Users, Database, Settings, TrendingUp, ShieldAlert, Search, RefreshCcw, ArrowLeft, Save, Gift, } from "lucide-react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { api, adminApi } from "@/lib/api"; import { useStore } from "@/lib/store"; import { formatNumber } from "@/lib/utils"; interface Analytics { users: { total: number; with_wallet: number; active_30d: number }; transactions: { total_earned: number; total_spent: number; total_count: number; }; requests: { total: number; pending: number; approved: number; declined: number; }; } interface User { id: string; plexUsername: string; isAdmin: boolean; totalEarned: number; totalSpent: number; } interface SystemSettings { creditsPerMinute: number; movieRequestCost: number; tvRequestCost: number; tvPerSeasonCost: number; minWatchPercent: number; minWatchMinutes: number; } export default function AdminPage() { const router = useRouter(); const { user, isAuthenticated } = useStore(); const [analytics, setAnalytics] = useState(null); const [users, setUsers] = useState([]); const [settings, setSettings] = useState(null); const [searchQuery, setSearchQuery] = useState(""); const [isLoading, setIsLoading] = useState(true); const [isSavingSettings, setIsSavingSettings] = useState(false); const [rewardAmount, setRewardAmount] = useState>({}); useEffect(() => { if (!isAuthenticated || !user?.isAdmin) { router.push("/dashboard"); return; } loadData(); }, [isAuthenticated, user, router]); const loadData = async () => { try { const [analyticsRes, usersRes, settingsRes] = await Promise.all([ adminApi.getAnalytics(), adminApi.getUsers(), adminApi.getSettings(), ]); setAnalytics(analyticsRes.data); setUsers(usersRes.data.users || []); setSettings(settingsRes.data); } catch { toast.error("Failed to load coop secrets"); } finally { setIsLoading(false); } }; const handleUpdateSettings = async (e: React.FormEvent) => { e.preventDefault(); if (!settings) return; setIsSavingSettings(true); try { await adminApi.updateSettings(settings); toast.success("Barn rules updated!"); } catch { toast.error("Failed to update rules"); } finally { setIsSavingSettings(false); } }; const adjustUser = async (userId: string, amount: number, reason: string) => { try { await adminApi.adjustUser(userId, amount, reason); toast.success("Feathers adjusted!"); loadData(); } catch { toast.error("Failed to adjust nest"); } }; const backfillUser = async (userId: string) => { toast.info("Scouring the barn for old eggs..."); try { await adminApi.backfillUser(userId); toast.success("Backfill complete!"); loadData(); } catch { toast.error("Backfill failed"); } }; const toggleAdmin = async (userId: string, isAdmin: boolean) => { try { await api.patch(`/admin/users/${userId}`, { isAdmin }); toast.success(isAdmin ? "Promoted to Rooster!" : "Demoted to Hen."); loadData(); } catch { toast.error("Failed to change pecking order"); } }; const filteredUsers = users.filter((u) => u.plexUsername?.toLowerCase().includes(searchQuery.toLowerCase()), ); if (isLoading) return (
Peeking into the coop...
); return (

COOP CONTROL

The Farmer's Desk

THE FLOCK BARN RULES EGG STATS

The Peeps

setSearchQuery(e.target.value)} className="rounded-full border-2 border-foreground pl-10 focus-visible:ring-primary h-12" />
{filteredUsers.map((u) => (
{u.plexUsername} {u.isAdmin && ( Rooster )}
Nest Egg: {formatNumber(u.totalEarned - u.totalSpent)}{" "} $COOP
setRewardAmount({ ...rewardAmount, [u.id]: e.target.value, }) } className="h-8 w-20 border-0 bg-transparent text-center font-bold focus-visible:ring-0" />
))}
The Barn Rules Change the physics of the coop {settings && (

Earning Logic

setSettings({ ...settings, creditsPerMinute: Number(e.target.value), }) } className="border-2 border-foreground h-12 font-bold focus-visible:ring-primary" />
setSettings({ ...settings, minWatchPercent: Number(e.target.value), }) } className="border-2 border-foreground h-12 font-bold focus-visible:ring-primary" />

Request Costs

setSettings({ ...settings, movieRequestCost: Number(e.target.value), }) } className="border-2 border-foreground h-12 font-bold focus-visible:ring-primary" />
setSettings({ ...settings, tvRequestCost: Number(e.target.value), }) } className="border-2 border-foreground h-12 font-bold focus-visible:ring-primary" />
)}
Flock Size
{analytics?.users.total || 0}
Total $COOP
{formatNumber(analytics?.transactions.total_earned || 0)}
Requests
{analytics?.requests.total || 0}
Pending
{analytics?.requests.pending || 0}
); }