import { callAction, useSession } from "@agent-native/core/client/hooks"; import { useT } from "@agent-native/core/client/i18n"; import { buildSignInReturnHref } from "@agent-native/core/client/ui"; import { IconCheck, IconMailFast, IconX } from "@tabler/icons-react"; import { useEffect, useState } from "react"; import { useNavigate, useParams } from "react-router"; import { toast } from "sonner"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import enMessages from "@/i18n/en-US"; export function meta() { return [{ title: enMessages.inviteRoute.pageTitle }]; } interface InvitePayload { id: string; organizationId: string; organizationName: string; organizationBrandColor: string; email: string; role: string; invitedBy: string; expiresAt: string | null; acceptedAt: string | null; } export default function InviteAcceptRoute() { const t = useT(); const { token } = useParams<{ token: string }>(); const { session } = useSession(); const navigate = useNavigate(); const [loading, setLoading] = useState(true); const [invite, setInvite] = useState(null); const [error, setError] = useState(null); const [accepting, setAccepting] = useState(false); const [declineOpen, setDeclineOpen] = useState(false); useEffect(() => { let cancelled = false; async function load() { if (!token) { setError(t("inviteRoute.missingToken")); setLoading(false); return; } try { const json = await callAction<{ invite: InvitePayload | null; error?: string; }>("get-invite" as any, { token } as any, { method: "GET" }); if (cancelled) return; if (!json.invite) { setError(json.error ?? t("inviteRoute.notFound")); } else { setInvite(json.invite as InvitePayload); } } catch (err) { if (!cancelled) { setError( err instanceof Error ? err.message : t("inviteRoute.loadFailed"), ); } } finally { if (!cancelled) setLoading(false); } } load(); return () => { cancelled = true; }; }, [token]); async function handleAccept() { if (!token) return; setAccepting(true); try { await callAction("accept-invite" as any, { token } as any); toast.success( t("inviteRoute.joined", { team: invite?.organizationName ?? t("inviteRoute.theTeam"), }), ); navigate("/library", { replace: true }); } catch (err) { toast.error( err instanceof Error ? err.message : t("inviteRoute.acceptFailed"), ); } finally { setAccepting(false); } } async function handleDecline() { if (!token) return; try { await callAction("decline-invite" as any, { token } as any); toast.success(t("inviteRoute.declined")); navigate("/", { replace: true }); } catch (err) { toast.error( err instanceof Error ? err.message : t("inviteRoute.declineFailed"), ); } finally { setDeclineOpen(false); } } if (!session?.email) { return (
{t("inviteRoute.signInRequired")}

{t("inviteRoute.signInDescription")}

); } return (
{t("inviteRoute.invited")} {loading ? (
{t("inviteRoute.loading")}
) : error ? (
{error}
) : invite ? (
{invite.organizationName.slice(0, 1).toUpperCase()}
{invite.organizationName}
{t("inviteRoute.role")}{" "} {invite.role.replace("-", " ")}

{t("inviteRoute.invitedToJoin", { inviter: invite.invitedBy, team: invite.organizationName, })}

{invite.email !== session.email ? (
{t("inviteRoute.emailMismatch", { inviteEmail: invite.email, sessionEmail: session.email, })}
) : null}
) : null}
{t("inviteRoute.declineInvite")} {t("inviteRoute.declineDescription")} {t("inviteRoute.cancel")} {t("inviteRoute.decline")}
); }