"use client"; import { useI18n } from "@/components/I18nProvider"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { createBrowserClient } from "@supabase/ssr"; import { passwordUpdateSchema } from "@/shared/account"; export function PasswordForm({ recovery = false }: { recovery?: boolean }) { const { t } = useI18n(); const [current, setCurrent] = useState(""), [password, setPassword] = useState(""), [confirmation, setConfirmation] = useState(""), [nonce, setNonce] = useState(""), [needsNonce, setNeedsNonce] = useState(false), [error, setError] = useState(""), [message, setMessage] = useState(""), [busy, setBusy] = useState(false); const router = useRouter(); async function submit(event: React.FormEvent) { event.preventDefault(); setError(""); setMessage(""); const body = { password, ...(!recovery ? { currentPassword: current } : {}), ...(needsNonce ? { nonce } : {}), }; const valid = passwordUpdateSchema.safeParse(body); if (!valid.success) { setError(valid.error.issues[0].message); return; } if (password !== confirmation) { setError("Your passwords do not match."); return; } setBusy(true); try { const response = await fetch("/api/v1/auth/password", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(valid.data), signal: AbortSignal.timeout(30000), }); const data = await response.json(); if (!response.ok) { if (data.needsReauthentication) { const client = createBrowserClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!, ); const { error } = await client.auth.reauthenticate(); if (error) throw error; setNeedsNonce(true); setMessage( "Check your email for a verification code, then enter it below to finish.", ); return; } throw new Error(data.error || "Could not update your password"); } setCurrent(""); setPassword(""); setConfirmation(""); setNonce(""); setNeedsNonce(false); setMessage(data.message); if (recovery) { router.replace("/settings?password=updated"); router.refresh(); } } catch (e) { setError((e as Error).message); } finally { setBusy(false); } } return (
); }