import { useState } from "react"; import { useNavigate } from "react-router-dom"; import { userApi } from "../lib/api"; import { useAppContext } from "../App"; const PERSONA_MAX = 500; export default function Settings() { const { user, updateUser, setStatusMessage } = useAppContext(); const navigate = useNavigate(); const [displayName, setDisplayName] = useState(user?.displayName ?? ""); const [currentPassword, setCurrentPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [persona, setPersona] = useState(user?.persona ?? ""); const [error, setError] = useState(""); const [success, setSuccess] = useState(""); const [saving, setSaving] = useState(false); const personaRemaining = PERSONA_MAX - persona.length; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(""); setSuccess(""); if (displayName.length < 3 || displayName.length > 30) { setError("Display Name must be between 3-30 characters."); return; } const changingPassword = currentPassword || newPassword || confirmPassword; if (changingPassword) { if (!currentPassword) { setError("Current password is required to change your password."); return; } if (!newPassword) { setError("New password is required."); return; } if (newPassword.length < 8) { setError("New password must be at least 8 characters."); return; } if (newPassword !== confirmPassword) { setError("New passwords do not match."); return; } } if (persona.length > PERSONA_MAX) { setError(`Persona must be ${PERSONA_MAX} characters or fewer.`); return; } setSaving(true); try { const body: Record = { displayName, persona, }; if (changingPassword) { body.currentPassword = currentPassword; body.password = newPassword; } const updatedUser = await userApi.updateSettings(body); setSuccess("Settings saved successfully."); setStatusMessage("Settings updated."); setCurrentPassword(""); setNewPassword(""); setConfirmPassword(""); // Update React context + localStorage in one place updateUser(updatedUser); } catch (err) { setError(err instanceof Error ? err.message : "Failed to save settings."); } finally { setSaving(false); } }; return (
// USER SETTINGS
ACCOUNT CONFIGURATION
Signed in as {user?.email}
Email address cannot be changed. Contact your administrator.
{error && (
// ERROR: {error}
)} {success && (
// SUCCESS: {success}
)}
setDisplayName(e.target.value)} className="w-full px-4 py-2 bg-bg-tertiary border border-border-default rounded text-text-primary font-mono focus:outline-none focus:border-border-highlight" minLength={3} maxLength={30} required />
--- PASSWORD ---
setCurrentPassword(e.target.value)} className="w-full px-4 py-2 bg-bg-tertiary border border-border-default rounded text-text-primary font-mono focus:outline-none focus:border-border-highlight" autoComplete="current-password" />
setNewPassword(e.target.value)} className="w-full px-4 py-2 bg-bg-tertiary border border-border-default rounded text-text-primary font-mono focus:outline-none focus:border-border-highlight" autoComplete="new-password" />
setConfirmPassword(e.target.value)} className="w-full px-4 py-2 bg-bg-tertiary border border-border-default rounded text-text-primary font-mono focus:outline-none focus:border-border-highlight" autoComplete="new-password" />
--- PERSONA ---