"use client"; import Link from "next/link"; import { useEffect, useRef, useState } from "react"; import { api } from "@/lib/client-api"; import { useI18n } from "./I18nProvider"; import type { ManagedAccount, AccountAppealRecord, } from "@/shared/account-controls"; import styles from "@/app/ban/appeal/page.module.css"; export function AccountAppeal() { const { locale } = useI18n(); const l = (en: string, ru: string) => (locale === "ru" ? ru : en); const [data, setData] = useState<{ account: ManagedAccount; appeals: AccountAppealRecord[]; } | null>(null); const [error, setError] = useState(""); const [message, setMessage] = useState(""); const [loading, setLoading] = useState(true); const [reason, setReason] = useState(""); const [busy, setBusy] = useState(false); const lock = useRef(false); useEffect(() => { let active = true; api<{ account: ManagedAccount; appeals: AccountAppealRecord[] }>( "ban/appeal", ) .then((result) => { if (active) setData(result); }) .catch((e) => { if (active) setError((e as Error).message); }) .finally(() => { if (active) setLoading(false); }); return () => { active = false; }; }, []); async function run(operation: () => Promise) { if (lock.current) return; lock.current = true; setBusy(true); setError(""); try { await operation(); } catch (e) { setError((e as Error).message); } finally { lock.current = false; setBusy(false); } } async function reload() { setData(await api("ban/appeal")); setLoading(false); } const current = data?.appeals.find( (a) => a.status_version === data.account.status_version, ); return (
{error && (

{error}

)} {message && (

{message}

)} {loading && !error && (

{l("Loading account status…", "Загрузка состояния аккаунта…")}

)}
{l("Read the guide", "Открыть руководство")}
{data && ( <>

{data.account.account_status === "active" ? l("Your account is active", "Ваш аккаунт активен") : data.account.account_status === "banned" ? l("Your account is banned", "Ваш аккаунт заблокирован") : data.account.account_status === "deleting" ? l( "Account deletion is pending", "Ожидается удаление аккаунта", ) : l( "Your account is deactivated", "Ваш аккаунт деактивирован", )}

{data.account.account_reason && ( <> {l("Reason", "Причина")}

{data.account.account_reason}

)} {data.account.account_status === "active" ? ( {l("Continue playing", "Продолжить играть")} ) : (

{l( "Normal account access, uploads and API keys are blocked. You can still read the docs, view this page and sign out.", "Обычный доступ к аккаунту, загрузки и ключи API заблокированы. Вы можете читать документацию, открывать эту страницу и выходить из аккаунта.", )}

)} {data.account.account_status === "deactivated" && (

{l( "An Admin must restore a deactivated account. Ban appeals are available only for banned accounts. Contact the team through the community links below.", "Деактивированный аккаунт может восстановить только администратор. Апелляции доступны только при блокировке. Свяжитесь с командой через ссылки сообщества внизу.", )}

)} {data.account.account_status === "deleting" && (

{l( "An Admin must finish this action. A deleted account cannot be appealed or recovered here.", "Администратор должен завершить это действие. Удалённый аккаунт нельзя восстановить или обжаловать здесь.", )}

)}
{data.account.account_status === "banned" && !current && (
{ e.preventDefault(); void run(async () => { await api("ban/appeal", { reason }); setReason(""); setMessage( l( "Appeal sent. A Moderator or Admin will review it.", "Апелляция отправлена. Её рассмотрит модератор или администратор.", ), ); await reload(); }); }} >

{l("Appeal this ban", "Обжаловать блокировку")}

{l( "Explain what happened and why the ban should be reconsidered. You can submit one appeal for each ban. Staff will leave their decision here.", "Расскажите, что произошло и почему блокировку стоит пересмотреть. Для каждой блокировки можно подать одну апелляцию. Решение команды появится здесь.", )}