Last active
March 18, 2021 09:15
-
-
Save PaGury/1b5b4d5df13d4fdf520cea8b89553cc2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type FormValues = { | |
email: string; | |
password: string; | |
passwordMatch: string; | |
}; | |
export const Signup = () => { | |
const tAuth = useTranslations('auth'); | |
const tForm = useTranslations('tranverse'); | |
const { mutate, isLoading, isError } = useRegisterMutation(); | |
const { handleSubmit, watch, components } = useAppForm<FormValues>(); | |
const { | |
Input, | |
} = components; | |
const onSubmit = useCallback((values: FormValues) => { | |
mutate({ | |
input: { | |
password: values.password, | |
email: values.email, | |
username: 'empty', | |
} | |
}); | |
}, []); | |
const password = useRef({}); | |
password.current = watch('password', ''); | |
return ( | |
<motion.div | |
initial={{ opacity: 0 }} | |
animate={{ opacity: 1 }} | |
exit={{ opacity: 0 }}> | |
<form onSubmit={handleSubmit(onSubmit)}> | |
<Title bold ultra>{tAuth.translate('SignupTitle')}</Title> | |
<Margin top={10}> | |
<Text type={TypographyType.secondary}>{tAuth.translate('FillYourSignupInformations')}</Text> | |
</Margin> | |
<Margin top={50}> | |
<Input | |
autoFocus | |
noMargin | |
name="email" | |
options={{ required: true, pattern: emailRegex }} | |
text={tForm.getInputText('form.email')} | |
/> | |
</Margin> | |
<Input | |
name="password" | |
options={{ required: true, validate: passwordMatcher }} | |
text={tForm.getInputText('form.password')} | |
inputProps={{ type: 'password' }} | |
/> | |
<Input | |
name="passwordMatch" | |
options={{ required: true, validate: value => value === password.current }} | |
text={tForm.getInputText('form.passwordMatch')} | |
inputProps={{ type: 'password' }} | |
/> | |
<Margin align="right"> | |
<Link to="/signin">Connectez-vous</Link> | |
</Margin> | |
<Margin top={30} align="right"> | |
<Button isLoading={isLoading} type="submit">S'inscrire</Button> | |
</Margin> | |
<Margin top={40} bottom={30} align="center" className={$.SocialConnectorSpacer}> | |
<Text small ultra type={TypographyType.secondary}>ou s'inscrire avec</Text> | |
</Margin> | |
<SocialConnectors /> | |
</form> | |
</motion.div> | |
); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useCallback } from "react"; | |
import { FieldErrors, RegisterOptions, useForm, UseFormMethods } from "react-hook-form"; | |
import { Margin } from "@Components/Global/Gabarit/Gabarit"; | |
import { Label } from "@Components/Global/Label/Label"; | |
import { Input as RawInput } from "@Components/Global/Input/Input"; | |
type AnyFormValue = Record<string, any>; | |
type RenderProps<FormValues extends AnyFormValue, ExtendedProps extends {}> = { | |
hasError: boolean; | |
autoFocus?: boolean; | |
name: keyof FormValues; | |
options?: RegisterOptions; | |
register: UseFormMethods<FormValues>['register']; | |
text: { | |
label: string; | |
error?: string; | |
placeholder?: string; | |
hint?: string; | |
}; | |
inputProps?: ExtendedProps; | |
}; | |
type FormControllerProps<FormValues extends AnyFormValue, ExtendedProps extends {}> = { | |
autoFocus?: boolean; | |
name: keyof FormValues; | |
noMargin?: boolean; | |
register: UseFormMethods<FormValues>['register']; | |
errors: FieldErrors<FormValues>; | |
options?: RegisterOptions; | |
render: (props: RenderProps<FormValues, ExtendedProps>) => JSX.Element; | |
text: { | |
label: string; | |
error?: string; | |
placeholder?: string; | |
hint?: string; | |
}; | |
inputProps?: ExtendedProps; | |
}; | |
const FormController = <FormValues extends AnyFormValue, ExtendedProps extends {}> | |
(props: FormControllerProps<FormValues, ExtendedProps>) => { | |
const { | |
errors, | |
name, | |
register, | |
render, | |
text, | |
autoFocus, | |
noMargin, | |
options = {}, | |
inputProps, | |
} = props; | |
const { | |
label, | |
error, | |
hint, | |
} = text; | |
const hasError = !!errors[name]; | |
const errorMessage = hasError ? error : undefined; | |
return ( | |
<Margin top={noMargin ? 0 : 15}> | |
<Label | |
required={!!options.required} | |
error={errorMessage} | |
hint={hint} | |
input={ | |
render({ | |
hasError, | |
name, | |
register, | |
text, | |
autoFocus, | |
options, | |
inputProps, | |
}) | |
}> | |
{label} | |
</Label> | |
</Margin> | |
); | |
}; | |
export const useFormController = <T extends AnyFormValue, ExtendedProps extends {}>( | |
register: UseFormMethods<T>['register'], | |
errors: UseFormMethods<T>['errors'], | |
render: FormControllerProps<T, ExtendedProps>['render'], | |
) => { | |
type RawProps = FormControllerProps<AnyFormValue, ExtendedProps>; | |
type OmitKeys = 'render' | 'register' | 'errors'; | |
const registerRef = React.useRef(register); | |
registerRef.current = register; | |
const errorsRef = React.useRef(errors); | |
errorsRef.current = errors; | |
const renderRef = React.useRef(render); | |
renderRef.current = render; | |
type Props = Omit<RawProps, OmitKeys>; | |
const PrefilledFormController = useCallback((props: Props) => ( | |
<FormController | |
render={render} | |
register={registerRef.current} | |
errors={errorsRef.current} | |
{...props} | |
/> | |
), []); | |
return PrefilledFormController; | |
}; | |
export const useAppForm = <T extends AnyFormValue>() => { | |
const form = useForm<T>(); | |
type ExtendedInputProps = { | |
type: 'text' | 'password'; | |
}; | |
const Input = useFormController<T, ExtendedInputProps>( | |
form.register, | |
form.errors, | |
({ name, autoFocus, hasError, register, options, text: { placeholder }, inputProps }) => ( | |
<RawInput | |
autoFocus={autoFocus} | |
hasError={hasError} | |
name={name as string} | |
ref={register(options)} | |
placeholder={placeholder} | |
type={inputProps?.type ?? 'text'} | |
/> | |
) | |
); | |
return { | |
...form, | |
components: { | |
Input, | |
}, | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment