"use client"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useSession } from "next-auth/react"; import { useEffect, useState } from "react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Input } from "@/components/ui/input"; import { Separator } from "@/components/ui/separator"; import { PlayerAvatar } from "@/components/PlayerAvatar"; import { onAppEvent } from "@/lib/events"; type PlayerData = { ops: { name: string; uuid: string; level: number }[]; whitelist: { name: string; uuid: string }[]; banned: { name: string; uuid: string; reason: string }[]; }; type MetricEntry = { ts: string; players?: string[] }; export function PlayerDrawer() { const { data: session } = useSession(); const queryClient = useQueryClient(); const [name, setName] = useState(null); const [banReason, setBanReason] = useState(""); useEffect(() => onAppEvent("player:open", ({ name }) => setName(name)), []); useEffect(() => { if (!name) return; const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") setName(null); }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [name]); const authed = !!session; const players = useQuery({ queryKey: ["players"], queryFn: () => fetch("/api/players").then((r) => r.json()), enabled: authed && !!name, staleTime: 10_000, }); // Use existing analytics cache (last entry) to determine online now const analytics = queryClient.getQueryData(["analytics", 6]); const onlineNow = (analytics && analytics.length > 0 ? analytics[analytics.length - 1].players || [] : []) as string[]; const isOp = !!name && !!players.data?.ops.some((p) => p.name === name); const isWhitelisted = !!name && !!players.data?.whitelist.some((p) => p.name === name); const bannedEntry = (name && players.data?.banned.find((p) => p.name === name)) || null; const isBanned = !!bannedEntry; const isOnline = !!name && onlineNow.includes(name); const action = useMutation({ mutationFn: async (params: { action: string; reason?: string }) => { if (!name) throw new Error("No player selected"); const res = await fetch("/api/players", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ action: params.action, player: name, reason: params.reason }), }); const data = await res.json(); if (!res.ok) throw new Error(data.error); return data; }, onSuccess: (data) => { toast.success(data.response || "Done"); setBanReason(""); queryClient.invalidateQueries({ queryKey: ["players"] }); }, onError: (err) => toast.error("Action failed", { description: err.message }), }); if (!name) return null; return (
{ if (e.target === e.currentTarget) setName(null); }} >
); }