import { FormEventHandler, useState, VFC } from 'react'; import { Button, styled, TextField } from '@mui/material'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { useNavigate } from 'react-router'; import useQueryParams from 'hooks/useQueryParams'; import AuthOptions from './common/AuthOptions/AuthOptions'; import DividerText from 'component/common/DividerText/DividerText'; import { Alert } from '@mui/material'; import { LOGIN_BUTTON, LOGIN_EMAIL_ID, LOGIN_PASSWORD_ID } from 'utils/testIds'; import PasswordField from 'component/common/PasswordField/PasswordField'; import { useAuthApi } from 'hooks/api/actions/useAuthApi/useAuthApi'; import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser'; import { IAuthEndpointDetailsResponse } from 'hooks/api/getters/useAuth/useAuthEndpoint'; import { AuthenticationError, BadRequestError, NotFoundError, } from 'utils/apiUtils'; import { contentSpacingY } from 'themes/themeStyles'; interface IPasswordAuthProps { authDetails: IAuthEndpointDetailsResponse; redirect: string; } const StyledAlert = styled(Alert)(({ theme }) => ({ color: theme.palette.error.main, marginBottom: theme.spacing(1), })); const StyledDiv = styled('div')(({ theme }) => ({ ...contentSpacingY(theme), display: 'flex', flexDirection: 'column', })); const PasswordAuth: VFC = ({ authDetails, redirect }) => { const navigate = useNavigate(); const { refetchUser } = useAuthUser(); const params = useQueryParams(); const [username, setUsername] = useState(params.get('email') || ''); const [password, setPassword] = useState(''); const { passwordAuth } = useAuthApi(); const [errors, setErrors] = useState<{ usernameError?: string; passwordError?: string; apiError?: string; }>({}); const handleSubmit: FormEventHandler = async evt => { evt.preventDefault(); if (!username) { setErrors(prev => ({ ...prev, usernameError: 'This is a required field', })); } if (!password) { setErrors(prev => ({ ...prev, passwordError: 'This is a required field', })); } if (!password || !username) { return; } try { await passwordAuth(authDetails.path, username, password); refetchUser(); navigate(redirect, { replace: true }); } catch (error: any) { if ( error instanceof NotFoundError || error instanceof BadRequestError ) { setErrors(prev => ({ ...prev, apiError: 'Invalid login details', })); setPassword(''); setUsername(''); } else if (error instanceof AuthenticationError) { setErrors({ apiError: 'Invalid password and username combination.', }); } else { setErrors({ apiError: 'Unknown error while trying to authenticate.', }); } } }; const renderLoginForm = () => { const { usernameError, passwordError, apiError } = errors; return ( {apiError} } /> setUsername(evt.target.value)} value={username} error={Boolean(usernameError)} helperText={usernameError} autoComplete="username" data-testid={LOGIN_EMAIL_ID} variant="outlined" size="small" autoFocus /> setPassword(evt.target.value)} name="password" id="password" value={password} error={Boolean(passwordError)} helperText={passwordError} autoComplete="current-password" data-testid={LOGIN_PASSWORD_ID} /> } /> ); }; const { options = [] } = authDetails; return ( <> 0} show={ <> } /> {renderLoginForm()} } elseShow={renderLoginForm()} /> ); }; export default PasswordAuth;