import { memo, useCallback, useContext, useMemo, useState } from 'react'; import { toast } from 'react-toastify'; import ForwardIcon from '@mui/icons-material/Forward'; import { Box, Button, Paper, Typography } from '@mui/material'; import * as AuthenticationApi from 'components/routing/authentication'; import { useRequest } from 'alova/client'; import type { ValidateFieldsError } from 'async-validator'; import { LanguageSelector, ValidatedPasswordField, ValidatedTextField } from 'components'; import { AuthenticationContext } from 'contexts/authentication'; import { PROJECT_NAME } from 'env'; import { useI18nContext } from 'i18n/i18n-react'; import type { SignInRequest } from 'types'; import { onEnterCallback, updateValue } from 'utils'; import { SIGN_IN_REQUEST_VALIDATOR, validate } from 'validators'; const SignIn = memo(() => { const authenticationContext = useContext(AuthenticationContext); const { LL } = useI18nContext(); const [signInRequest, setSignInRequest] = useState({ username: '', password: '' }); const [processing, setProcessing] = useState(false); const [fieldErrors, setFieldErrors] = useState(); const { send: callSignIn } = useRequest( (request: SignInRequest) => AuthenticationApi.signIn(request), { immediate: false } ).onSuccess((response) => { if (response.data) { authenticationContext.signIn(response.data.access_token); } }); // Memoize callback to prevent recreation on every render const updateLoginRequestValue = useMemo( () => updateValue((updater) => setSignInRequest( updater as unknown as (prevState: SignInRequest) => SignInRequest ) ), [] ); const signIn = useCallback(async () => { await callSignIn(signInRequest).catch((event: Error) => { if (event.message === 'Unauthorized') { toast.warning(LL.INVALID_LOGIN()); } else { toast.error(LL.ERROR() + ' ' + event.message); } setProcessing(false); }); }, [callSignIn, signInRequest, LL]); const validateAndSignIn = useCallback(async () => { setProcessing(true); SIGN_IN_REQUEST_VALIDATOR.messages({ required: LL.IS_REQUIRED('%s') }); try { await validate(SIGN_IN_REQUEST_VALIDATOR, signInRequest); await signIn(); } catch (error) { setFieldErrors(error as ValidateFieldsError); setProcessing(false); } }, [signInRequest, signIn, LL]); // Memoize callback to prevent recreation on every render const submitOnEnter = useMemo(() => onEnterCallback(signIn), [signIn]); return ( theme.breakpoints.values.sm} > ({ textAlign: 'center', padding: theme.spacing(2), paddingTop: '172px', backgroundImage: 'url("/app/icon.png")', backgroundRepeat: 'no-repeat', backgroundPosition: '50% ' + theme.spacing(2), width: '100%' })} > {PROJECT_NAME} ); }); export default SignIn;