// components/account/PasswordChange.tsx "use client"; import { useEffect, useState } from "react"; type Me = { id: string; username?: string | null; email?: string | null; }; export default function PasswordChange() { const [current, setCurrent] = useState(""); const [next, setNext] = useState(""); const [next2, setNext2] = useState(""); const [identifier, setIdentifier] = useState(""); // email OR username (sent to API) const [needIdentifier, setNeedIdentifier] = useState(false); const [busy, setBusy] = useState(false); const [msg, setMsg] = useState(null); // Try to auto-fill identifier from /api/account useEffect(() => { (async () => { try { const r = await fetch("/api/account", { credentials: "include", cache: "no-store" }); const j = await r.json().catch(() => ({})); const me: Me | undefined = j?.user ?? j?.data ?? undefined; const id = (me?.email || me?.username || "").trim(); if (id) { setIdentifier(id); setNeedIdentifier(false); } else { setNeedIdentifier(true); } } catch { // If it fails, we'll let the user type it setNeedIdentifier(true); } })(); }, []); const onSave = async () => { setMsg(null); if (next !== next2) { setMsg("New passwords do not match."); return; } if (next.length < 8) { setMsg("Password must be at least 8 characters."); return; } if (!identifier.trim()) { setNeedIdentifier(true); setMsg("Please enter your email or username."); return; } setBusy(true); try { const r = await fetch("/api/account/password", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ current, next, identifier: identifier.trim() }), }); const j = await r.json().catch(() => ({} as any)); if (!r.ok) { setMsg(j?.error ? (j?.debug ? `${j.error} (${j.debug})` : j.error) : "Password change failed"); return; } setMsg("Password updated."); setCurrent(""); setNext(""); setNext2(""); } catch (e: any) { setMsg(e?.message || "Password change failed"); } finally { setBusy(false); } }; return (

Change Password

{needIdentifier && ( )}
{msg &&
{msg}
}
); }