import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { isTokenExpired } from '@documenso/lib/utils/token-verification'; import { prisma } from '@documenso/prisma'; import { trpc } from '@documenso/trpc/react'; import { Button } from '@documenso/ui/primitives/button'; import { useToast } from '@documenso/ui/primitives/use-toast'; import { Trans, useLingui } from '@lingui/react/macro'; import { useState } from 'react'; import { Link } from 'react-router'; import type { Route } from './+types/team.verify.email.$token'; export async function loader({ params }: Route.LoaderArgs) { const { token } = params; if (!token) { return { state: 'InvalidLink', } as const; } const teamEmailVerification = await prisma.teamEmailVerification.findUnique({ where: { token, }, select: { email: true, completed: true, expiresAt: true, team: { select: { name: true, }, }, }, }); if (!teamEmailVerification || isTokenExpired(teamEmailVerification.expiresAt)) { return { state: 'InvalidLink', } as const; } if (teamEmailVerification.completed) { return { state: 'AlreadyCompleted', teamName: teamEmailVerification.team.name, } as const; } return { state: 'Pending', token, email: teamEmailVerification.email, teamName: teamEmailVerification.team.name, } as const; } export default function VerifyTeamEmailPage({ loaderData }: Route.ComponentProps) { const data = loaderData; if (data.state === 'InvalidLink') { return (

Invalid link

This link is invalid or has expired. Please contact your team to resend a verification.

); } if (data.state === 'AlreadyCompleted') { return (

Team email already verified!

You have already verified your email address for {data.teamName}.

); } return ; } type PendingTeamEmailVerificationProps = { token: string; email: string; teamName: string; }; const PendingTeamEmailVerification = ({ token, email, teamName }: PendingTeamEmailVerificationProps) => { const { t } = useLingui(); const { toast } = useToast(); const [isVerified, setIsVerified] = useState(false); const { mutateAsync: completeTeamEmailVerification, isPending } = trpc.team.email.verification.complete.useMutation({ onSuccess: () => setIsVerified(true), onError: (err) => { const error = AppError.parseError(err); if (error.code === AppErrorCode.ALREADY_EXISTS) { toast({ title: t`Email already in use`, description: t`This email is already being used as a team email. Please contact your team for assistance.`, variant: 'destructive', duration: 10000, }); return; } toast({ title: t`Something went wrong`, description: t`We were unable to verify this email at this time. Please try again later.`, variant: 'destructive', duration: 10000, }); }, }); if (isVerified) { return (

Team email verified!

You have verified your email address for {teamName}.

); } return (

Verify team email

{teamName} would like to use {email} as their team email.

They will be able to view documents associated with this email.

Do not proceed if you are unsure about this request.

); };