fix: fix SignInUpForm Continue button being disabled (#5185)

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Thaïs
2024-04-26 16:27:40 +02:00
committed by GitHub
parent e1d0b26cf9
commit 8beec03762
2 changed files with 44 additions and 25 deletions

View File

@ -13,11 +13,13 @@ import { useSignInWithMicrosoft } from '@/auth/sign-in-up/hooks/useSignInWithMic
import { useWorkspaceFromInviteHash } from '@/auth/sign-in-up/hooks/useWorkspaceFromInviteHash'; import { useWorkspaceFromInviteHash } from '@/auth/sign-in-up/hooks/useWorkspaceFromInviteHash';
import { isRequestingCaptchaTokenState } from '@/captcha/states/isRequestingCaptchaTokenState'; import { isRequestingCaptchaTokenState } from '@/captcha/states/isRequestingCaptchaTokenState';
import { authProvidersState } from '@/client-config/states/authProvidersState'; import { authProvidersState } from '@/client-config/states/authProvidersState';
import { captchaProviderState } from '@/client-config/states/captchaProviderState';
import { Loader } from '@/ui/feedback/loader/components/Loader'; import { Loader } from '@/ui/feedback/loader/components/Loader';
import { MainButton } from '@/ui/input/button/components/MainButton'; import { MainButton } from '@/ui/input/button/components/MainButton';
import { TextInput } from '@/ui/input/components/TextInput'; import { TextInput } from '@/ui/input/components/TextInput';
import { ActionLink } from '@/ui/navigation/link/components/ActionLink.tsx'; import { ActionLink } from '@/ui/navigation/link/components/ActionLink.tsx';
import { AnimatedEaseIn } from '@/ui/utilities/animation/components/AnimatedEaseIn'; import { AnimatedEaseIn } from '@/ui/utilities/animation/components/AnimatedEaseIn';
import { isDefined } from '~/utils/isDefined';
import { Logo } from '../../components/Logo'; import { Logo } from '../../components/Logo';
import { Title } from '../../components/Title'; import { Title } from '../../components/Title';
@ -47,6 +49,7 @@ const StyledInputContainer = styled.div`
`; `;
export const SignInUpForm = () => { export const SignInUpForm = () => {
const captchaProvider = useRecoilValue(captchaProviderState);
const isRequestingCaptchaToken = useRecoilValue( const isRequestingCaptchaToken = useRecoilValue(
isRequestingCaptchaTokenState, isRequestingCaptchaTokenState,
); );
@ -117,6 +120,27 @@ export const SignInUpForm = () => {
const theme = useTheme(); const theme = useTheme();
const shouldWaitForCaptchaToken =
signInUpStep !== SignInUpStep.Init &&
isDefined(captchaProvider?.provider) &&
isRequestingCaptchaToken;
const isEmailStepSubmitButtonDisabledCondition =
signInUpStep === SignInUpStep.Email &&
(form.watch('email').length === 0 || shouldWaitForCaptchaToken);
// TODO: isValid is actually a proxy function. If it is not rendered the first time, react might not trigger re-renders
// We make the isValid check synchronous and update a reactState to make sure this does not happen
const isPasswordStepSubmitButtonDisabledCondition =
signInUpStep === SignInUpStep.Password &&
(!form.formState.isValid ||
form.formState.isSubmitting ||
shouldWaitForCaptchaToken);
const isSubmitButtonDisabled =
isEmailStepSubmitButtonDisabledCondition ||
isPasswordStepSubmitButtonDisabledCondition;
return ( return (
<> <>
<AnimatedEaseIn> <AnimatedEaseIn>
@ -245,17 +269,7 @@ export const SignInUpForm = () => {
form.handleSubmit(submitCredentials)(); form.handleSubmit(submitCredentials)();
}} }}
Icon={() => form.formState.isSubmitting && <Loader />} Icon={() => form.formState.isSubmitting && <Loader />}
disabled={ disabled={isSubmitButtonDisabled}
signInUpStep === SignInUpStep.Init
? false
: isRequestingCaptchaToken
? true
: signInUpStep === SignInUpStep.Email
? !form.watch('email')
: !form.watch('email') ||
!form.watch('password') ||
form.formState.isSubmitting
}
fullWidth fullWidth
/> />
</StyledForm> </StyledForm>

View File

@ -1,27 +1,23 @@
import { FocusEventHandler, forwardRef, useRef } from 'react'; import { FocusEventHandler, forwardRef, ForwardRefRenderFunction } from 'react';
import { Key } from 'ts-key-enum'; import { Key } from 'ts-key-enum';
import { import {
TextInputV2, TextInputV2,
TextInputV2ComponentProps, TextInputV2ComponentProps,
} from '@/ui/input/components/TextInputV2'; } from '@/ui/input/components/TextInputV2';
import { InputHotkeyScope } from '@/ui/input/types/InputHotkeyScope';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { isDefined } from '~/utils/isDefined';
import { InputHotkeyScope } from '../types/InputHotkeyScope';
export type TextInputComponentProps = TextInputV2ComponentProps & { export type TextInputComponentProps = TextInputV2ComponentProps & {
disableHotkeys?: boolean; disableHotkeys?: boolean;
}; };
const TextInputComponent = ({ const TextInputComponent: ForwardRefRenderFunction<
onFocus, HTMLInputElement,
onBlur, TextInputComponentProps
disableHotkeys = false, > = ({ onFocus, onBlur, disableHotkeys = false, ...props }, ref) => {
...props
}: TextInputComponentProps): JSX.Element => {
const inputRef = useRef<HTMLInputElement>(null);
const { const {
goBackToPreviousHotkeyScope, goBackToPreviousHotkeyScope,
setHotkeyScopeAndMemorizePreviousScope, setHotkeyScopeAndMemorizePreviousScope,
@ -46,14 +42,23 @@ const TextInputComponent = ({
useScopedHotkeys( useScopedHotkeys(
[Key.Escape, Key.Enter], [Key.Escape, Key.Enter],
() => { () => {
inputRef.current?.blur(); if (isDefined(ref) && 'current' in ref) {
ref.current?.blur();
}
}, },
InputHotkeyScope.TextInput, InputHotkeyScope.TextInput,
{ enabled: !disableHotkeys }, { enabled: !disableHotkeys },
); );
// eslint-disable-next-line react/jsx-props-no-spreading return (
return <TextInputV2 {...props} onFocus={handleFocus} onBlur={handleBlur} />; <TextInputV2
ref={ref}
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
onFocus={handleFocus}
onBlur={handleBlur}
/>
);
}; };
export const TextInput = forwardRef(TextInputComponent); export const TextInput = forwardRef(TextInputComponent);