Merge pull request #405 from Discours/feature/parse-email-errors
Feature/parse email errors
This commit is contained in:
commit
5812c84756
|
@ -2,7 +2,7 @@
|
|||
"$schema": "https://biomejs.dev/schemas/1.5.3/schema.json",
|
||||
"files": {
|
||||
"include": ["*.tsx", "*.ts", "*.js", "*.json"],
|
||||
"ignore": ["./dist", "./node_modules", ".husky", "docs", "gen"]
|
||||
"ignore": ["./dist", "./node_modules", ".husky", "docs", "gen", "*.d.ts"]
|
||||
},
|
||||
"vcs": {
|
||||
"defaultBranch": "dev",
|
||||
|
@ -29,7 +29,7 @@
|
|||
}
|
||||
},
|
||||
"linter": {
|
||||
"ignore": ["*.scss", "*.md", ".DS_Store", "*.svg"],
|
||||
"ignore": ["*.scss", "*.md", ".DS_Store", "*.svg", "*.d.ts"],
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"all": true,
|
||||
|
|
|
@ -377,6 +377,9 @@
|
|||
"There are unsaved changes in your publishing settings. Are you sure you want to leave the page without saving?": "There are unsaved changes in your publishing settings. Are you sure you want to leave the page without saving?",
|
||||
"This comment has not yet been rated": "This comment has not yet been rated",
|
||||
"This email is": "This email is",
|
||||
"This email is not verified": "This email is not verified",
|
||||
"This email is verified": "This email is verified",
|
||||
"This email is registered": "This email is registered",
|
||||
"This functionality is currently not available, we would like to work on this issue. Use the download link.": "This functionality is currently not available, we would like to work on this issue. Use the download link.",
|
||||
"This month": "This month",
|
||||
"This post has not been rated yet": "This post has not been rated yet",
|
||||
|
@ -407,7 +410,6 @@
|
|||
"Upload video": "Upload video",
|
||||
"Upload": "Upload",
|
||||
"Uploading image": "Uploading image",
|
||||
"User with this email already exists": "User with this email already exists",
|
||||
"Username": "Username",
|
||||
"Userpic": "Userpic",
|
||||
"Users": "Users",
|
||||
|
|
|
@ -399,6 +399,9 @@
|
|||
"There are unsaved changes in your publishing settings. Are you sure you want to leave the page without saving?": "В настройках публикации есть несохраненные изменения. Уверены, что хотите покинуть страницу без сохранения?",
|
||||
"This comment has not yet been rated": "Этот комментарий еще пока никто не оценил",
|
||||
"This email is": "Этот email",
|
||||
"This email is not verified": "Этот email не подтвержден",
|
||||
"This email is verified": "Этот email подтвержден",
|
||||
"This email is registered": "Этот email уже зарегистрирован",
|
||||
"This functionality is currently not available, we would like to work on this issue. Use the download link.": "В данный момент этот функционал не доступен, бы работаем над этой проблемой. Воспользуйтесь загрузкой по ссылке.",
|
||||
"This month": "За месяц",
|
||||
"This post has not been rated yet": "Эту публикацию еще пока никто не оценил",
|
||||
|
@ -429,7 +432,6 @@
|
|||
"Upload video": "Загрузить видео",
|
||||
"Upload": "Загрузить",
|
||||
"Uploading image": "Загружаем изображение",
|
||||
"User with this email already exists": "Пользователь с таким email уже существует",
|
||||
"Username": "Имя пользователя",
|
||||
"Userpic": "Аватар",
|
||||
"Users": "Пользователи",
|
||||
|
|
|
@ -74,7 +74,7 @@ export const AuthorBadge = (props: Props) => {
|
|||
on(
|
||||
() => props.isFollowed,
|
||||
() => {
|
||||
setIsFollowed(props.isFollowed.value)
|
||||
setIsFollowed(props.isFollowed?.value)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
|
|
@ -198,6 +198,14 @@
|
|||
border-color: var(--background-color-invert);
|
||||
}
|
||||
}
|
||||
|
||||
&.info,
|
||||
&.info a {
|
||||
color: var(--secondary-color);
|
||||
border-color: var(--secondary-color);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.title {
|
||||
|
|
|
@ -13,6 +13,7 @@ type Props = {
|
|||
errorMessage?: (error: string) => void
|
||||
onInput: (value: string) => void
|
||||
variant?: 'login' | 'registration'
|
||||
disableAutocomplete?: boolean
|
||||
}
|
||||
|
||||
export const PasswordField = (props: Props) => {
|
||||
|
@ -69,7 +70,7 @@ export const PasswordField = (props: Props) => {
|
|||
id="password"
|
||||
name="password"
|
||||
disabled={props.disabled}
|
||||
autocomplete="current-password"
|
||||
autocomplete={props.disableAutocomplete ? 'one-time-code' : 'current-password'}
|
||||
type={showPassword() ? 'text' : 'password'}
|
||||
placeholder={props.placeholder || t('Password')}
|
||||
onInput={(event) => handleInputChange(event.currentTarget.value)}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import type { JSX } from 'solid-js'
|
||||
import { Show, createEffect, createMemo, createSignal } from 'solid-js'
|
||||
import type { AuthModalSearchParams } from './types'
|
||||
|
||||
import { clsx } from 'clsx'
|
||||
import { Show, createEffect, createMemo, createSignal } from 'solid-js'
|
||||
|
||||
import { useLocalize } from '../../../context/localize'
|
||||
import { useSession } from '../../../context/session'
|
||||
|
@ -17,6 +17,8 @@ import { email, setEmail } from './sharedLogic'
|
|||
|
||||
import styles from './AuthModal.module.scss'
|
||||
|
||||
type EmailStatus = 'not verified' | 'verified' | 'registered' | ''
|
||||
|
||||
type FormFields = {
|
||||
fullName: string
|
||||
email: string
|
||||
|
@ -39,22 +41,12 @@ export const RegisterForm = () => {
|
|||
const [isSubmitting, setIsSubmitting] = createSignal(false)
|
||||
const [isSuccess, setIsSuccess] = createSignal(false)
|
||||
const [validationErrors, setValidationErrors] = createSignal<ValidationErrors>({})
|
||||
const [infoEmailMessage, setInfoEmailMessage] = createSignal<boolean>(false)
|
||||
const [passwordError, setPasswordError] = createSignal<string>()
|
||||
const [emailStatus, setEmailStatus] = createSignal<string>('')
|
||||
|
||||
const authFormRef: { current: HTMLFormElement } = { current: null }
|
||||
|
||||
const checkEmail = async (address: string) => {
|
||||
const result: string = await isRegistered(address)
|
||||
if (result) setEmailStatus((_s) => result)
|
||||
}
|
||||
|
||||
const handleEmailBlur = () => {
|
||||
if (validateEmail(email())) {
|
||||
checkEmail(email())
|
||||
}
|
||||
}
|
||||
|
||||
const handleNameInput = (newName: string) => {
|
||||
setFullName(newName)
|
||||
}
|
||||
|
@ -100,8 +92,8 @@ export const RegisterForm = () => {
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
setIsSubmitting(true)
|
||||
setInfoEmailMessage(false)
|
||||
try {
|
||||
const opts = {
|
||||
given_name: cleanName,
|
||||
|
@ -111,26 +103,7 @@ export const RegisterForm = () => {
|
|||
redirect_uri: window.location.origin,
|
||||
}
|
||||
const { errors } = await signUp(opts)
|
||||
if (errors?.some((error) => error.message.includes('has already signed up'))) {
|
||||
setValidationErrors((prev) => ({
|
||||
...prev,
|
||||
email: (
|
||||
<>
|
||||
{t('User with this email already exists')},{' '}
|
||||
<span
|
||||
class={'link'}
|
||||
onClick={() =>
|
||||
changeSearchParams({
|
||||
mode: 'login',
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('sign in')}
|
||||
</span>
|
||||
</>
|
||||
),
|
||||
}))
|
||||
}
|
||||
if (errors) return
|
||||
setIsSuccess(true)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
@ -138,9 +111,65 @@ export const RegisterForm = () => {
|
|||
setIsSubmitting(false)
|
||||
}
|
||||
}
|
||||
createEffect(() => {
|
||||
console.debug(emailStatus())
|
||||
})
|
||||
|
||||
const handleCheckEmailStatus = (status: EmailStatus | string) => {
|
||||
switch (status) {
|
||||
case 'not verified':
|
||||
setInfoEmailMessage(true)
|
||||
setValidationErrors((prev) => ({
|
||||
...prev,
|
||||
email: (
|
||||
<>
|
||||
{t('This email is not verified')},{' '}
|
||||
<span
|
||||
class="link"
|
||||
onClick={() => resendVerifyEmail({ email: email(), identifier: 'basic_signup' })}
|
||||
>
|
||||
{t('resend confirmation link')}
|
||||
</span>
|
||||
</>
|
||||
),
|
||||
}))
|
||||
break
|
||||
|
||||
case 'verified':
|
||||
setInfoEmailMessage(true)
|
||||
setValidationErrors((prev) => ({
|
||||
email: (
|
||||
<>
|
||||
{t('This email is verified')},{' '}
|
||||
<span class="link" onClick={() => changeSearchParams({ mode: 'login' })}>
|
||||
{t('enter')}
|
||||
</span>
|
||||
</>
|
||||
),
|
||||
}))
|
||||
break
|
||||
case 'registered':
|
||||
setValidationErrors((prev) => ({
|
||||
...prev,
|
||||
email: (
|
||||
<>
|
||||
{t('This email is registered')},{'. '}
|
||||
<span class="link" onClick={() => changeSearchParams({ mode: 'send-reset-link' })}>
|
||||
{t('Set the new password').toLocaleLowerCase()}
|
||||
</span>
|
||||
</>
|
||||
),
|
||||
}))
|
||||
break
|
||||
default:
|
||||
setInfoEmailMessage(false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const handleEmailBlur = async () => {
|
||||
if (validateEmail(email())) {
|
||||
const checkResult = await isRegistered(email())
|
||||
handleCheckEmailStatus(checkResult)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -162,63 +191,37 @@ export const RegisterForm = () => {
|
|||
name="fullName"
|
||||
type="text"
|
||||
placeholder={t('Full name')}
|
||||
autocomplete=""
|
||||
autocomplete="one-time-code"
|
||||
onInput={(event) => handleNameInput(event.currentTarget.value)}
|
||||
/>
|
||||
<label for="name">{t('Full name')}</label>
|
||||
<Show when={!emailStatus() && validationErrors().fullName}>
|
||||
<Show when={validationErrors().fullName}>
|
||||
<div class={styles.validationError}>{validationErrors().fullName}</div>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class={clsx('pretty-form__item', {
|
||||
'pretty-form__item--error': validationErrors().email,
|
||||
'pretty-form__item--error': validationErrors().email && !infoEmailMessage(),
|
||||
})}
|
||||
>
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
autocomplete="email"
|
||||
autocomplete="one-time-code"
|
||||
type="email"
|
||||
value={email()}
|
||||
placeholder={t('Email')}
|
||||
onInput={(event) => handleEmailInput(event.currentTarget.value)}
|
||||
onBlur={handleEmailBlur}
|
||||
/>
|
||||
<label for="email">{t('Email')}</label>
|
||||
<div class={styles.validationError}>{validationErrors().email}</div>
|
||||
<Show when={Boolean(emailStatus())}>
|
||||
{t('This email is')} {emailStatus() ? t(emailStatus()) : ''},{' '}
|
||||
</Show>
|
||||
<Show when={emailStatus() === 'verfied'}>
|
||||
<span class="link" onClick={() => changeSearchParams({ mode: 'login' })}>
|
||||
{t('enter')}
|
||||
</span>
|
||||
</Show>
|
||||
<Show when={emailStatus() === 'not verfied'}>
|
||||
<span
|
||||
class="link"
|
||||
onClick={() => resendVerifyEmail({ email: email(), identifier: 'basic_signup' })}
|
||||
>
|
||||
{t('resend confirmation link')}
|
||||
</span>
|
||||
</Show>
|
||||
<Show when={emailStatus() === 'registered'}>
|
||||
<span
|
||||
class="link"
|
||||
onClick={() =>
|
||||
changeSearchParams({
|
||||
mode: 'send-reset-link',
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('Set the new password').toLocaleLowerCase()}
|
||||
</span>
|
||||
</Show>
|
||||
<div class={clsx(styles.validationError, styles.info, { [styles.info]: infoEmailMessage() })}>
|
||||
{validationErrors().email}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<PasswordField
|
||||
disableAutocomplete={true}
|
||||
disabled={Boolean(emailStatus())}
|
||||
errorMessage={(err) => setPasswordError(err)}
|
||||
onInput={(value) => setPassword(value)}
|
||||
|
|
Loading…
Reference in New Issue
Block a user