"use client"; import { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import { useI18n } from "@/lib/i18n/useI18n"; type InviteInfo = { email: string; role: string; org: { id: string; name: string; slug: string }; expiresAt: string; }; type InviteAcceptFormProps = { token: string; initialInvite?: InviteInfo | null; initialError?: string | null; }; export default function InviteAcceptForm({ token, initialInvite = null, initialError = null, }: InviteAcceptFormProps) { const router = useRouter(); const { t } = useI18n(); const cleanedToken = token.trim(); const [invite, setInvite] = useState(initialInvite); const [loading, setLoading] = useState(!initialInvite && !initialError); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(initialError); const [name, setName] = useState(""); const [password, setPassword] = useState(""); useEffect(() => { if (initialInvite || initialError) { setLoading(false); return; } let alive = true; async function loadInvite() { setLoading(true); setError(null); try { const res = await fetch(`/api/invites/${encodeURIComponent(cleanedToken)}`, { cache: "no-store", }); const data = await res.json().catch(() => ({})); if (!res.ok || !data.ok) { throw new Error(data.error || t("invite.error.notFound")); } if (alive) setInvite(data.invite); } catch (err: unknown) { const message = err instanceof Error ? err.message : null; if (alive) setError(message || t("invite.error.notFound")); } finally { if (alive) setLoading(false); } } loadInvite(); return () => { alive = false; }; }, [cleanedToken, initialInvite, initialError, t]); async function onSubmit(e: React.FormEvent) { e.preventDefault(); setError(null); setSubmitting(true); try { const res = await fetch(`/api/invites/${encodeURIComponent(cleanedToken)}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name, password }), }); const data = await res.json().catch(() => ({})); if (!res.ok || !data.ok) { throw new Error(data.error || t("invite.error.acceptFailed")); } router.push("/machines"); router.refresh(); } catch (err: unknown) { const message = err instanceof Error ? err.message : null; setError(message || t("invite.error.acceptFailed")); } finally { setSubmitting(false); } } if (loading) { return (
{t("invite.loading")}
); } if (!invite) { return (
{error || t("invite.notFound")}
); } return (

{t("invite.joinTitle", { org: invite.org.name })}

{t("invite.acceptCopy", { email: invite.email, role: invite.role })}

setName(e.target.value)} autoComplete="name" />
setPassword(e.target.value)} autoComplete="new-password" />
{error &&
{error}
}
); }