diff --git a/web/modals/account/log-in-modal.react.js b/web/account/log-in-form.react.js similarity index 66% copy from web/modals/account/log-in-modal.react.js copy to web/account/log-in-form.react.js index 177cdabfc..1aa7a79ad 100644 --- a/web/modals/account/log-in-modal.react.js +++ b/web/account/log-in-form.react.js @@ -1,158 +1,155 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { logInActionTypes, logIn } from 'lib/actions/user-actions'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors'; import { - validEmailRegex, oldValidUsernameRegex, + validEmailRegex, } from 'lib/shared/account-utils'; import type { LogInExtraInfo, LogInStartingPayload, } from 'lib/types/account-types'; import { useDispatchActionPromise, useServerCall, } from 'lib/utils/action-utils'; -import Button from '../../components/button.react'; -import { useSelector } from '../../redux/redux-utils'; -import { webLogInExtraInfoSelector } from '../../selectors/account-selectors'; -import Input from '../input.react'; -import { useModalContext } from '../modal-provider.react'; -import Modal from '../modal.react'; -import css from './user-settings-modal.css'; +import Button from '../components/button.react'; +import css from '../modals/account/user-settings-modal.css'; +import Input from '../modals/input.react'; +import { useModalContext } from '../modals/modal-provider.react'; +import { useSelector } from '../redux/redux-utils'; +import { webLogInExtraInfoSelector } from '../selectors/account-selectors'; const loadingStatusSelector = createLoadingStatusSelector(logInActionTypes); -function LoginModal(): React.Node { +function LoginForm(): React.Node { const inputDisabled = useSelector(loadingStatusSelector) === 'loading'; const loginExtraInfo = useSelector(webLogInExtraInfoSelector); const callLogIn = useServerCall(logIn); const dispatchActionPromise = useDispatchActionPromise(); const modalContext = useModalContext(); const [username, setUsername] = React.useState(''); const [password, setPassword] = React.useState(''); const [errorMessage, setErrorMessage] = React.useState(''); const usernameInputRef = React.useRef(); const passwordInputRef = React.useRef(); React.useEffect(() => { usernameInputRef.current?.focus(); }, []); const onUsernameChange = React.useCallback(e => { invariant(e.target instanceof HTMLInputElement, 'target not input'); setUsername(e.target.value); }, []); const onPasswordChange = React.useCallback(e => { invariant(e.target instanceof HTMLInputElement, 'target not input'); setPassword(e.target.value); }, []); const logInAction = React.useCallback( async (extraInfo: LogInExtraInfo) => { try { const result = await callLogIn({ username, password, ...extraInfo, }); modalContext.clearModal(); return result; } catch (e) { if (e.message === 'invalid_parameters') { setUsername(''); setErrorMessage(`user doesn't exist`); usernameInputRef.current?.focus(); } else if (e.message === 'invalid_credentials') { setPassword(''); setErrorMessage('wrong password'); passwordInputRef.current?.focus(); } else { setUsername(''); setPassword(''); setErrorMessage('unknown error'); usernameInputRef.current?.focus(); } throw e; } }, [callLogIn, modalContext, password, username], ); const onSubmit = React.useCallback( (event: SyntheticEvent) => { event.preventDefault(); if (username.search(validEmailRegex) > -1) { setUsername(''); setErrorMessage('usernames only, not emails'); usernameInputRef.current?.focus(); return; } else if (username.search(oldValidUsernameRegex) === -1) { setUsername(''); setErrorMessage('alphanumeric usernames only'); usernameInputRef.current?.focus(); return; } const extraInfo = loginExtraInfo(); dispatchActionPromise( logInActionTypes, logInAction(extraInfo), undefined, ({ calendarQuery: extraInfo.calendarQuery }: LogInStartingPayload), ); }, [dispatchActionPromise, logInAction, loginExtraInfo, username], ); return ( - -
-
-
-
Username
-
- -
-
-
-
Password
-
- -
+
+ +
+
Username
+
+
-
- -
{errorMessage}
+
+
+
Password
+
+
- -
- +
+
+ +
{errorMessage}
+
+ +
); } -export default LoginModal; +export default LoginForm; diff --git a/web/modals/account/log-in-modal.react.js b/web/modals/account/log-in-modal.react.js index 177cdabfc..9527bae25 100644 --- a/web/modals/account/log-in-modal.react.js +++ b/web/modals/account/log-in-modal.react.js @@ -1,158 +1,18 @@ // @flow -import invariant from 'invariant'; import * as React from 'react'; -import { logInActionTypes, logIn } from 'lib/actions/user-actions'; -import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors'; -import { - validEmailRegex, - oldValidUsernameRegex, -} from 'lib/shared/account-utils'; -import type { - LogInExtraInfo, - LogInStartingPayload, -} from 'lib/types/account-types'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils'; - -import Button from '../../components/button.react'; -import { useSelector } from '../../redux/redux-utils'; -import { webLogInExtraInfoSelector } from '../../selectors/account-selectors'; -import Input from '../input.react'; +import LoginForm from '../../account/log-in-form.react.js'; import { useModalContext } from '../modal-provider.react'; import Modal from '../modal.react'; -import css from './user-settings-modal.css'; -const loadingStatusSelector = createLoadingStatusSelector(logInActionTypes); function LoginModal(): React.Node { - const inputDisabled = useSelector(loadingStatusSelector) === 'loading'; - const loginExtraInfo = useSelector(webLogInExtraInfoSelector); - const callLogIn = useServerCall(logIn); - const dispatchActionPromise = useDispatchActionPromise(); const modalContext = useModalContext(); - - const [username, setUsername] = React.useState(''); - const [password, setPassword] = React.useState(''); - const [errorMessage, setErrorMessage] = React.useState(''); - - const usernameInputRef = React.useRef(); - const passwordInputRef = React.useRef(); - - React.useEffect(() => { - usernameInputRef.current?.focus(); - }, []); - - const onUsernameChange = React.useCallback(e => { - invariant(e.target instanceof HTMLInputElement, 'target not input'); - setUsername(e.target.value); - }, []); - - const onPasswordChange = React.useCallback(e => { - invariant(e.target instanceof HTMLInputElement, 'target not input'); - setPassword(e.target.value); - }, []); - - const logInAction = React.useCallback( - async (extraInfo: LogInExtraInfo) => { - try { - const result = await callLogIn({ - username, - password, - ...extraInfo, - }); - modalContext.clearModal(); - return result; - } catch (e) { - if (e.message === 'invalid_parameters') { - setUsername(''); - setErrorMessage(`user doesn't exist`); - usernameInputRef.current?.focus(); - } else if (e.message === 'invalid_credentials') { - setPassword(''); - setErrorMessage('wrong password'); - passwordInputRef.current?.focus(); - } else { - setUsername(''); - setPassword(''); - setErrorMessage('unknown error'); - usernameInputRef.current?.focus(); - } - throw e; - } - }, - [callLogIn, modalContext, password, username], - ); - - const onSubmit = React.useCallback( - (event: SyntheticEvent) => { - event.preventDefault(); - - if (username.search(validEmailRegex) > -1) { - setUsername(''); - setErrorMessage('usernames only, not emails'); - usernameInputRef.current?.focus(); - return; - } else if (username.search(oldValidUsernameRegex) === -1) { - setUsername(''); - setErrorMessage('alphanumeric usernames only'); - usernameInputRef.current?.focus(); - return; - } - - const extraInfo = loginExtraInfo(); - dispatchActionPromise( - logInActionTypes, - logInAction(extraInfo), - undefined, - ({ calendarQuery: extraInfo.calendarQuery }: LogInStartingPayload), - ); - }, - [dispatchActionPromise, logInAction, loginExtraInfo, username], - ); - return ( -
-
-
-
Username
-
- -
-
-
-
Password
-
- -
-
-
- -
{errorMessage}
-
-
-
+
); } export default LoginModal;