add focus & fix styles for auth forms errors (#156)
* add focus & fix styles for auth forms errors * refactor by review comments * minor changes: let ref -> const ref: { current }, additional typings --------- Co-authored-by: bniwredyc <bniwredyc@gmail.com>
This commit is contained in:
parent
8e5f34eb85
commit
4fea17a2ce
|
@ -28,6 +28,8 @@ export const ForgotPasswordForm = () => {
|
|||
const [validationErrors, setValidationErrors] = createSignal<ValidationErrors>({})
|
||||
const [isUserNotFount, setIsUserNotFound] = createSignal(false)
|
||||
|
||||
const authFormRef: { current: HTMLFormElement } = { current: null }
|
||||
|
||||
const handleSubmit = async (event: Event) => {
|
||||
event.preventDefault()
|
||||
|
||||
|
@ -47,6 +49,10 @@ export const ForgotPasswordForm = () => {
|
|||
const isValid = Object.keys(newValidationErrors).length === 0
|
||||
|
||||
if (!isValid) {
|
||||
authFormRef.current
|
||||
.querySelector<HTMLInputElement>(`input[name="${Object.keys(newValidationErrors)[0]}"]`)
|
||||
.focus()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -66,7 +72,11 @@ export const ForgotPasswordForm = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} class={clsx(styles.authForm, styles.authFormForgetPassword)}>
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
class={clsx(styles.authForm, styles.authFormForgetPassword)}
|
||||
ref={(el) => (authFormRef.current = el)}
|
||||
>
|
||||
<div>
|
||||
<h4>{t('Forgot password?')}</h4>
|
||||
<div class={styles.authSubtitle}>{t('Everything is ok, please give us your email address')}</div>
|
||||
|
@ -95,7 +105,11 @@ export const ForgotPasswordForm = () => {
|
|||
<Show when={validationErrors().email}>
|
||||
<div class={styles.validationError}>{validationErrors().email}</div>
|
||||
</Show>
|
||||
<div class="pretty-form__item">
|
||||
<div
|
||||
class={clsx('pretty-form__item', {
|
||||
'pretty-form__item--error': validationErrors().email
|
||||
})}
|
||||
>
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
|
|
|
@ -33,6 +33,8 @@ export const LoginForm = () => {
|
|||
const [isLinkSent, setIsLinkSent] = createSignal(false)
|
||||
const [showPassword, setShowPassword] = createSignal(false)
|
||||
|
||||
const authFormRef: { current: HTMLFormElement } = { current: null }
|
||||
|
||||
const {
|
||||
actions: { showSnackbar }
|
||||
} = useSnackbar()
|
||||
|
@ -57,9 +59,11 @@ export const LoginForm = () => {
|
|||
|
||||
const handleSendLinkAgainClick = async (event: Event) => {
|
||||
event.preventDefault()
|
||||
|
||||
setIsLinkSent(true)
|
||||
setIsEmailNotConfirmed(false)
|
||||
setSubmitError('')
|
||||
setIsLinkSent(true)
|
||||
|
||||
const result = await signSendLink({ email: email(), lang: lang(), template: 'email_confirmation' })
|
||||
if (result.error) setSubmitError(result.error)
|
||||
}
|
||||
|
@ -85,6 +89,11 @@ export const LoginForm = () => {
|
|||
|
||||
if (Object.keys(newValidationErrors).length > 0) {
|
||||
setValidationErrors(newValidationErrors)
|
||||
|
||||
authFormRef.current
|
||||
.querySelector<HTMLInputElement>(`input[name="${Object.keys(newValidationErrors)[0]}"]`)
|
||||
.focus()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -92,18 +101,23 @@ export const LoginForm = () => {
|
|||
|
||||
try {
|
||||
await signIn({ email: email(), password: password() })
|
||||
|
||||
hideModal()
|
||||
|
||||
showSnackbar({ body: t('Welcome!') })
|
||||
} catch (error) {
|
||||
if (error instanceof ApiError) {
|
||||
if (error.code === 'email_not_confirmed') {
|
||||
setSubmitError(t('Please, confirm email'))
|
||||
|
||||
setIsEmailNotConfirmed(true)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (error.code === 'user_not_found') {
|
||||
setSubmitError(t('Something went wrong, check email and password'))
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +129,7 @@ export const LoginForm = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} class={styles.authForm}>
|
||||
<form onSubmit={handleSubmit} class={styles.authForm} ref={(el) => (authFormRef.current = el)}>
|
||||
<div>
|
||||
<AuthModalHeader modalType="login" />
|
||||
<Show when={submitError()}>
|
||||
|
@ -131,7 +145,11 @@ export const LoginForm = () => {
|
|||
<Show when={isLinkSent()}>
|
||||
<div class={styles.authInfo}>{t('Link sent, check your email')}</div>
|
||||
</Show>
|
||||
<div class="pretty-form__item">
|
||||
<div
|
||||
class={clsx('pretty-form__item', {
|
||||
'pretty-form__item--error': validationErrors().email
|
||||
})}
|
||||
>
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
|
@ -147,7 +165,11 @@ export const LoginForm = () => {
|
|||
<div class={styles.validationError}>{validationErrors().email}</div>
|
||||
</Show>
|
||||
|
||||
<div class="pretty-form__item">
|
||||
<div
|
||||
class={clsx('pretty-form__item', {
|
||||
'pretty-form__item--error': validationErrors().password
|
||||
})}
|
||||
>
|
||||
<input
|
||||
id="password"
|
||||
name="password"
|
||||
|
|
|
@ -15,7 +15,7 @@ import { validateEmail } from '../../../utils/validateEmail'
|
|||
import { AuthModalHeader } from './AuthModalHeader'
|
||||
|
||||
type FormFields = {
|
||||
name: string
|
||||
fullName: string
|
||||
email: string
|
||||
password: string
|
||||
}
|
||||
|
@ -28,12 +28,14 @@ export const RegisterForm = () => {
|
|||
const { emailChecks } = useEmailChecks()
|
||||
|
||||
const [submitError, setSubmitError] = createSignal('')
|
||||
const [name, setName] = createSignal('')
|
||||
const [fullName, setFullName] = createSignal('')
|
||||
const [password, setPassword] = createSignal('')
|
||||
const [isSubmitting, setIsSubmitting] = createSignal(false)
|
||||
const [isSuccess, setIsSuccess] = createSignal(false)
|
||||
const [validationErrors, setValidationErrors] = createSignal<ValidationErrors>({})
|
||||
|
||||
const authFormRef: { current: HTMLFormElement } = { current: null }
|
||||
|
||||
const handleEmailInput = (newEmail: string) => {
|
||||
setValidationErrors(({ email: _notNeeded, ...rest }) => rest)
|
||||
setEmail(newEmail)
|
||||
|
@ -73,8 +75,8 @@ export const RegisterForm = () => {
|
|||
}
|
||||
|
||||
const handleNameInput = (newPasswordCopy: string) => {
|
||||
setValidationErrors(({ name: _notNeeded, ...rest }) => rest)
|
||||
setName(newPasswordCopy)
|
||||
setValidationErrors(({ fullName: _notNeeded, ...rest }) => rest)
|
||||
setFullName(newPasswordCopy)
|
||||
}
|
||||
|
||||
const handleSubmit = async (event: Event) => {
|
||||
|
@ -84,11 +86,11 @@ export const RegisterForm = () => {
|
|||
|
||||
const newValidationErrors: ValidationErrors = {}
|
||||
|
||||
const cleanName = name().trim()
|
||||
const cleanName = fullName().trim()
|
||||
const cleanEmail = email().trim()
|
||||
|
||||
if (!cleanName) {
|
||||
newValidationErrors.name = t('Please enter a name to sign your comments and publication')
|
||||
newValidationErrors.fullName = t('Please enter a name to sign your comments and publication')
|
||||
}
|
||||
|
||||
if (!cleanEmail) {
|
||||
|
@ -108,6 +110,10 @@ export const RegisterForm = () => {
|
|||
const isValid = Object.keys(newValidationErrors).length === 0 && !emailCheckResult
|
||||
|
||||
if (!isValid) {
|
||||
authFormRef.current
|
||||
.querySelector<HTMLInputElement>(`input[name="${Object.keys(newValidationErrors)[0]}"]`)
|
||||
.focus()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -135,7 +141,7 @@ export const RegisterForm = () => {
|
|||
return (
|
||||
<>
|
||||
<Show when={!isSuccess()}>
|
||||
<form onSubmit={handleSubmit} class={styles.authForm}>
|
||||
<form onSubmit={handleSubmit} class={styles.authForm} ref={(el) => (authFormRef.current = el)}>
|
||||
<div>
|
||||
<AuthModalHeader modalType="register" />
|
||||
<Show when={submitError()}>
|
||||
|
@ -145,7 +151,11 @@ export const RegisterForm = () => {
|
|||
</ul>
|
||||
</div>
|
||||
</Show>
|
||||
<div class="pretty-form__item">
|
||||
<div
|
||||
class={clsx('pretty-form__item', {
|
||||
'pretty-form__item--error': validationErrors().fullName
|
||||
})}
|
||||
>
|
||||
<input
|
||||
name="fullName"
|
||||
type="text"
|
||||
|
@ -153,12 +163,16 @@ export const RegisterForm = () => {
|
|||
autocomplete=""
|
||||
onInput={(event) => handleNameInput(event.currentTarget.value)}
|
||||
/>
|
||||
<label for="fullName">{t('Full name')}</label>
|
||||
<label for="name">{t('Full name')}</label>
|
||||
</div>
|
||||
<Show when={validationErrors().name}>
|
||||
<div class={styles.validationError}>{validationErrors().name}</div>
|
||||
<Show when={validationErrors().fullName}>
|
||||
<div class={styles.validationError}>{validationErrors().fullName}</div>
|
||||
</Show>
|
||||
<div class="pretty-form__item">
|
||||
<div
|
||||
class={clsx('pretty-form__item', {
|
||||
'pretty-form__item--error': validationErrors().email
|
||||
})}
|
||||
>
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
|
@ -188,7 +202,11 @@ export const RegisterForm = () => {
|
|||
</a>
|
||||
</div>
|
||||
</Show>
|
||||
<div class="pretty-form__item">
|
||||
<div
|
||||
class={clsx('pretty-form__item', {
|
||||
'pretty-form__item--error': validationErrors().password
|
||||
})}
|
||||
>
|
||||
<input
|
||||
id="password"
|
||||
name="password"
|
||||
|
|
|
@ -391,42 +391,6 @@ button {
|
|||
}
|
||||
|
||||
form {
|
||||
.pretty-form__item {
|
||||
position: relative;
|
||||
|
||||
input {
|
||||
padding-top: 1.4em;
|
||||
}
|
||||
|
||||
textarea {
|
||||
line-height: 1.4;
|
||||
}
|
||||
}
|
||||
|
||||
.pretty-form__item--with-button {
|
||||
margin-bottom: 1.6rem;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
*:first-child {
|
||||
flex: 1;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input[type='text'],
|
||||
input[type='email'],
|
||||
input[type='password'],
|
||||
|
@ -510,6 +474,48 @@ form {
|
|||
.form-message {
|
||||
@include font-size(1.2rem);
|
||||
}
|
||||
|
||||
.pretty-form__item {
|
||||
position: relative;
|
||||
|
||||
input {
|
||||
padding-top: 1.4em;
|
||||
}
|
||||
|
||||
textarea {
|
||||
line-height: 1.4;
|
||||
}
|
||||
}
|
||||
|
||||
.pretty-form__item--error {
|
||||
input {
|
||||
border-color: #d00820;
|
||||
}
|
||||
}
|
||||
|
||||
.pretty-form__item--with-button {
|
||||
margin-bottom: 1.6rem;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
*:first-child {
|
||||
flex: 1;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input--short {
|
||||
|
|
Loading…
Reference in New Issue
Block a user