import { useState, useEffect } from 'react' import { Helmet } from 'react-helmet-async' import { Field, Form, Formik, useFormikContext } from 'formik' import { Link, Navigate, useSearchParams, useNavigate } from 'react-router-dom' import { trpc, client } from '~/utils/trpc' import IVInputField from '~/components/IVInputField' import IVButton from '~/components/IVButton' import { isEmail } from '~/utils/validate' import { tryLogin } from '~/utils/auth' import useHasSession from '~/utils/useHasSession' import GoogleIcon from '~/icons/compiled/Google' import AuthPageHeader from '~/components/AuthPageHeader' import { useSetRecoilState } from 'recoil' import { redirectAfterLogin } from '~/components/LoginRedirect' export default function LoginPage() { const [shouldShowPassword, setShouldShowPassword] = useState(false) const [shouldShowMfaToken, setShouldShowMfaToken] = useState(false) const [hasError, setHasError] = useState(false) const navigate = useNavigate() const { hasSession, needsMfa } = useHasSession() const [searchParams] = useSearchParams() const prefilledEmail = searchParams.get('email') const integrations = trpc.useQuery(['dashboard.integrations']) { const externalRedirect = searchParams.get('redirect') const setRedirect = useSetRecoilState(redirectAfterLogin) useEffect(() => { if (externalRedirect) { setRedirect(externalRedirect) } }, [externalRedirect, setRedirect]) } if (hasSession) { return } if (needsMfa) { return } return (
Log in | Interval
initialValues={{ email: prefilledEmail || '', password: '', }} onSubmit={async (values, { setSubmitting }) => { setHasError(false) if (!shouldShowPassword) { // Check for SSO const { sso, needsMfa } = await client.query('auth.check', { email: values.email, }) if (integrations.data?.workos && sso) { const { workosOrganizationId } = sso const params = new URLSearchParams({ workosOrganizationId, }) window.location.assign(`/api/auth/sso/auth?${params}`) } else { setShouldShowPassword(true) setShouldShowMfaToken(!!integrations.data?.workos && needsMfa) setSubmitting(false) } return } try { const r = await tryLogin(values) if (r.ok) { if (shouldShowMfaToken) { navigate('/verify-mfa') } else { window.location.assign('/dashboard') } } else { setHasError(true) } } catch (err) { console.error(err) setHasError(true) setSubmitting(false) } }} validate={({ email, password }) => { if (!email.length) { return { email: 'Please enter your email address.' } } if (!isEmail(email)) { return { email: 'Please enter a valid email address.' } } if (shouldShowPassword && !password.length) { return { password: 'Please enter your password.' } } }} > {({ isSubmitting, isValid }) => (
{!shouldShowPassword && integrations.data?.workos && ( <>
Sign in with Google } className="w-full" />

or
)} {shouldShowPassword && ( )} {hasError && (
Invalid login, please try again.
)}
{shouldShowPassword ? ( <> Forgot password?
{ setShouldShowPassword(false) }} />
) : ( Create an account › )}
)}
) } function PasswordVisibleToken({ shouldShowPassword, }: { shouldShowPassword: boolean }) { const { touched, setFieldValue, setTouched } = useFormikContext<{ email: string password: string }>() useEffect(() => { if (touched.email && touched.password && !shouldShowPassword) { setFieldValue('password', '') setTouched({ email: false, password: false }, true) } }, [shouldShowPassword, touched, setFieldValue, setTouched]) return null }