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 }) => (
)}
)
}
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
}