import { useState } from 'react'; import { post } from '../lib/api'; // Server error code -> friendly copy. const ERRORS: Record = { missing_code: 'Enter your signup code.', invalid_code: "That code isn't valid. Double-check it with whoever gave it to you.", code_revoked: 'That code has been revoked. Ask for a new one.', code_used: 'That code has already been used.', code_expired: 'That code has expired. Ask for a new one.', invalid_username: 'Pick a username 2–24 characters long (letters, numbers, _ or -).', username_taken: 'That username is taken — try another.', missing_password: 'Enter a password.', password_too_short: 'Use at least 8 characters for your password.', password_mismatch: 'The passwords do not match.', }; export function Join() { const [code, setCode] = useState(''); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); const [busy, setBusy] = useState(false); const [err, setErr] = useState(null); const [doneUsername, setDoneUsername] = useState(null); const submit = async (e: React.FormEvent) => { e.preventDefault(); setBusy(true); setErr(null); if (password !== confirmPassword) { setErr(ERRORS.password_mismatch); setBusy(false); return; } try { const res = await post<{ ok: boolean; username: string }>('/join/redeem', { Code: code.trim(), Username: username.trim(), Password: password, }); setDoneUsername(res.username); } catch (e) { const key = (e as Error).message; setErr(ERRORS[key] ?? key); } finally { setBusy(false); } }; if (doneUsername) { return (

You're in, {doneUsername}! 🎉

Your account is ready. Launch the game through the DorkNet launcher and sign in with your username and password.

); } return (

Join the server

Got a signup code? Redeem it here to create your account, then sign in from the game.

{err && (
{err}
)}
); }