"use client"; import { useCallback, useEffect, useState } from "react"; import { api } from "./StartGame"; export type Appeal = { id: string; dataset_id: string; reason: string; state: string; review_reason: string | null; created_at: string; reviewed_at: string | null; }; export function MapAppeal({ id, strikes, bannedAt, banReason, onChange, }: { id: string; strikes: number; bannedAt: string | null; banReason: string | null; onChange: () => void; }) { const [appeals, setAppeals] = useState([]); const [reason, setReason] = useState(""); const [error, setError] = useState(""); const [busy, setBusy] = useState(false); const load = useCallback(async () => { try { setAppeals( (await api<{ appeals: Appeal[] }>(`datasets/${id}/appeals`)).appeals, ); } catch (e) { setError((e as Error).message); } }, [id]); useEffect(() => { load(); const timer = setInterval(load, 10000); return () => clearInterval(timer); }, [load]); async function submit(event: React.FormEvent) { event.preventDefault(); setBusy(true); setError(""); try { await api(`datasets/${id}/appeals`, { reason }); setReason(""); await load(); onChange(); } catch (e) { setError((e as Error).message); } finally { setBusy(false); } } return (

{bannedAt ? "Map unpublished · appeal required" : "Community report strikes"}

{strikes}/3 confirmed reports.{" "} {bannedAt ? "This map cannot be published until a moderator approves your appeal." : "Three confirmed reports automatically unpublish this map."}

{banReason &&

{banReason}

} {appeals.map((a) => (
Appeal: {a.state}

{a.reason}

{a.review_reason &&

Moderator feedback: {a.review_reason}

}
))} {bannedAt && (appeals.some((a) => a.state === "open") ? (

Your appeal is waiting for moderator review.

) : (