import React, { useMemo, useState } from "react"; import { createRoot } from "react-dom/client"; import "./support.css"; type FormState = { name: string; email: string; message: string; }; type Status = "idle" | "sending" | "success" | "error"; const tips = [ "Session code or lobby name", "What you were trying to do", "Anything that looked broken or confusing", ]; const contactNotes = [ "Messages are routed to the Negopoly support desk.", "Add an email if you want a reply.", "No account needed. Just send and go.", ]; const MAX_NAME_LENGTH = 80; const MAX_EMAIL_LENGTH = 120; const MAX_MESSAGE_LENGTH = 2000; function Support() { const [form, setForm] = useState({ name: "", email: "", message: "", }); const [status, setStatus] = useState("idle"); const [error, setError] = useState(null); const canSubmit = useMemo(() => { return ( status !== "sending" && form.name.trim().length > 0 && form.email.trim().length > 0 && form.message.trim().length > 0 ); }, [form, status]); const statusLabel = useMemo(() => { if (status === "success") return "Message sent. We'll follow up if you left contact info."; if (status === "error") return error ?? "Something went wrong. Try again in a moment."; if (status === "sending") return "Sending your message..."; return "We only use your contact info to reply to this request."; }, [status, error]); async function handleSubmit(event: React.FormEvent) { event.preventDefault(); if (!canSubmit) return; setStatus("sending"); setError(null); try { const res = await fetch("/api/support", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: form.name, email: form.email, message: form.message, }), }); const payload = await res.json().catch(() => ({})); if (!res.ok) { throw new Error(payload?.message ?? "Unable to send message."); } setStatus("success"); setForm({ name: "", email: "", message: "" }); } catch (err) { const message = err instanceof Error ? err.message : "Unable to send message."; setStatus("error"); setError(message); } } return (
NegoCity support desk
Back to NegoCity

Support, reports, and lost deals.

Tell us what went wrong, what you need, or where the Banker needs a hand. We will read every message that lands in the support vault.

What to include

    {tips.map((tip) => (
  • {tip}
  • ))}

How this works

    {contactNotes.map((note) => (
  • {note}
  • ))}

Need the rules instead?

Head to the full guide to get back into the game quickly.

View the rulebook

Send a message

{statusLabel}