parent
56a83dc8ba
commit
1d64d97f9f
|
@ -18,6 +18,7 @@
|
|||
"Add signature": "Add signature",
|
||||
"Add subtitle": "Add subtitle",
|
||||
"Add url": "Add url",
|
||||
"try": "попробуйте",
|
||||
"Add": "Add",
|
||||
"Address on Discours": "Address on Discours",
|
||||
"Album name": "Название aльбома",
|
||||
|
@ -144,7 +145,6 @@
|
|||
"Enter your new password": "Enter your new password",
|
||||
"Enter": "Enter",
|
||||
"Error": "Error",
|
||||
"Please give us your email address": "Please provide us your email address to get the password reset link",
|
||||
"Experience": "Experience",
|
||||
"FAQ": "Tips and suggestions",
|
||||
"Favorite topics": "Favorite topics",
|
||||
|
@ -254,7 +254,6 @@
|
|||
"Nothing here yet": "There's nothing here yet",
|
||||
"Nothing is here": "There is nothing here",
|
||||
"Notifications": "Notifications",
|
||||
"Now you can enter a new password, it must contain at least 8 characters and not be the same as the previous password": "Now you can enter a new password, it must contain at least 8 characters and not be the same as the previous password",
|
||||
"Or paste a link to an image": "Or paste a link to an image",
|
||||
"Ordered list": "Ordered list",
|
||||
"Our regular contributor": "Our regular contributor",
|
||||
|
@ -323,7 +322,7 @@
|
|||
"Self-publishing exists thanks to the help of wonderful people from all over the world. Thank you!": "Samizdat exists thanks to the help of wonderful people from all over the world. Thank you!",
|
||||
"Send link again": "Send link again",
|
||||
"Send": "Send",
|
||||
"Set the new password": "Set the new password",
|
||||
"Forgot password?": "Forgot password?",
|
||||
"Settings": "Settings",
|
||||
"Share publication": "Share publication",
|
||||
"Share": "Share",
|
||||
|
@ -524,5 +523,7 @@
|
|||
"video": "video",
|
||||
"view": "view",
|
||||
"viewsWithCount": "{count} {count, plural, one {view} other {views}}",
|
||||
"yesterday": "yesterday"
|
||||
"yesterday": "yesterday",
|
||||
"It's OK. Just enter your email to receive a link to change your password": "It's OK. Just enter your email to receive a link to change your password",
|
||||
"Restore password": "Restore password"
|
||||
}
|
||||
|
|
|
@ -150,7 +150,6 @@
|
|||
"Enter your new password": "Введите новый пароль",
|
||||
"Enter": "Войти",
|
||||
"Error": "Ошибка",
|
||||
"Please give us your email address": "Пожалуйста, укажите свою почту, чтобы получить ссылку для сброса пароля",
|
||||
"Experience": "Личный опыт",
|
||||
"FAQ": "Советы и предложения",
|
||||
"Favorite topics": "Избранные темы",
|
||||
|
@ -266,7 +265,6 @@
|
|||
"Nothing here yet": "Здесь пока ничего нет",
|
||||
"Nothing is here": "Здесь ничего нет",
|
||||
"Notifications": "Уведомления",
|
||||
"Now you can enter a new password, it must contain at least 8 characters and not be the same as the previous password": "Теперь можете ввести новый пароль, он должен содержать минимум 8 символов и не совпадать с предыдущим паролем",
|
||||
"Or paste a link to an image": "Или вставьте ссылку на изображение",
|
||||
"Ordered list": "Нумерованный список",
|
||||
"Our regular contributor": "Наш постоянный автор",
|
||||
|
@ -287,7 +285,7 @@
|
|||
"Pin": "Закрепить",
|
||||
"Platform Guide": "Гид по дискурсу",
|
||||
"Please check your email address": "Пожалуйста, проверьте введенный адрес почты",
|
||||
"Please check your inbox! We have sent a password reset link.": "Пожалуйста, проверьте ваш адрес почты, мы отправили ссылку для сброса пароля",
|
||||
"Please check your inbox! We have sent a password reset link.": "Пожалуйста, проверьте свою почту, мы отправили вам письмо со ссылкой для сброса пароля",
|
||||
"Please confirm your email to finish": "Подтвердите почту и действие совершится",
|
||||
"Please enter a name to sign your comments and publication": "Пожалуйста, введите имя, которое будет отображаться на сайте",
|
||||
"Please enter email": "Пожалуйста, введите почту",
|
||||
|
@ -328,7 +326,7 @@
|
|||
"Reports": "Репортажи",
|
||||
"Required": "Поле обязательно для заполнения",
|
||||
"Resend code": "Выслать подтверждение",
|
||||
"Set the new password": "Задать новый пароль",
|
||||
"Forgot password?": "Забыли пароль?",
|
||||
"Rules of the journal Discours": "Правила журнала Дискурс",
|
||||
"Save draft": "Сохранить черновик",
|
||||
"Save settings": "Сохранить настройки",
|
||||
|
@ -403,6 +401,7 @@
|
|||
"This email is": "Этот email",
|
||||
"This email is not verified": "Этот email не подтвержден",
|
||||
"This email is verified": "Этот email подтвержден",
|
||||
"try": "попробуйте",
|
||||
"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": "За месяц",
|
||||
|
@ -550,5 +549,7 @@
|
|||
"video": "видео",
|
||||
"view": "просмотр",
|
||||
"viewsWithCount": "{count} {count, plural, one {просмотр} few {просмотрa} other {просмотров}}",
|
||||
"yesterday": "вчера"
|
||||
"yesterday": "вчера",
|
||||
"It's OK. Just enter your email to receive a link to change your password": "Ничего страшного. Просто укажите свою почту, чтобы получить ссылку для смены пароля",
|
||||
"Restore password": "Восстановить пароль"
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
@include font-size(1.2rem);
|
||||
|
||||
color: var(--secondary-color);
|
||||
|
||||
// align-self: center;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.view {
|
||||
background: #fff;
|
||||
background: var(--background-color);
|
||||
min-height: 550px;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
|
@ -154,17 +154,6 @@
|
|||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.authInfo {
|
||||
font-weight: 400;
|
||||
font-size: smaller;
|
||||
margin-top: -2em;
|
||||
position: absolute;
|
||||
|
||||
.warn {
|
||||
color: #a00;
|
||||
}
|
||||
}
|
||||
|
||||
.authForm {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
@ -221,3 +210,7 @@
|
|||
line-height: 24px;
|
||||
margin-bottom: 52px;
|
||||
}
|
||||
|
||||
.submitError {
|
||||
margin: -1rem 0 -2rem;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ export const ChangePasswordForm = () => {
|
|||
event.preventDefault()
|
||||
setIsSubmitting(true)
|
||||
if (newPassword()) {
|
||||
await changePassword(newPassword(), searchParams()?.token)
|
||||
changePassword(newPassword(), searchParams()?.token)
|
||||
setTimeout(() => {
|
||||
setIsSubmitting(false)
|
||||
setIsSuccess(true)
|
||||
|
@ -60,11 +60,6 @@ export const ChangePasswordForm = () => {
|
|||
>
|
||||
<div>
|
||||
<h4>{t('Enter a new password')}</h4>
|
||||
<div class={styles.authSubtitle}>
|
||||
{t(
|
||||
'Now you can enter a new password, it must contain at least 8 characters and not be the same as the previous password',
|
||||
)}
|
||||
</div>
|
||||
<Show when={validationErrors()}>
|
||||
<div>{validationErrors().password}</div>
|
||||
</Show>
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
.title {
|
||||
font-size: 26px;
|
||||
line-height: 32px;
|
||||
font-weight: 700;
|
||||
color: #141414;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
margin-bottom: 52px;
|
||||
}
|
|
@ -17,19 +17,20 @@ export const EmailConfirm = () => {
|
|||
const [emailConfirmed, setEmailConfirmed] = createSignal(false)
|
||||
|
||||
createEffect(() => {
|
||||
const e = session()?.user?.email
|
||||
const v = session()?.user?.email_verified
|
||||
if (e) {
|
||||
setEmail(e.toLowerCase())
|
||||
if (v) setEmailConfirmed(v)
|
||||
const email = session()?.user?.email
|
||||
const isVerified = session()?.user?.email_verified
|
||||
|
||||
if (email) {
|
||||
setEmail(email.toLowerCase())
|
||||
if (isVerified) setEmailConfirmed(isVerified)
|
||||
if (authError()) {
|
||||
changeSearchParams({}, true)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
if (authError()) console.debug('[AuthModal.EmailConfirm] auth error:', authError())
|
||||
if (authError()) {
|
||||
console.debug('[AuthModal.EmailConfirm] auth error:', authError())
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { AuthModalSearchParams } from './types'
|
||||
|
||||
import { clsx } from 'clsx'
|
||||
import { Show, createSignal } from 'solid-js'
|
||||
import { JSX, Show, createEffect, createSignal } from 'solid-js'
|
||||
|
||||
import { useLocalize } from '../../../context/localize'
|
||||
import { useSession } from '../../../context/session'
|
||||
|
@ -27,12 +27,11 @@ type ValidationErrors = Partial<Record<keyof FormFields, string>>
|
|||
export const LoginForm = () => {
|
||||
const { changeSearchParams } = useRouter<AuthModalSearchParams>()
|
||||
const { t } = useLocalize()
|
||||
const [submitError, setSubmitError] = createSignal('')
|
||||
const [submitError, setSubmitError] = createSignal<string | JSX.Element>()
|
||||
const [isSubmitting, setIsSubmitting] = createSignal(false)
|
||||
const [password, setPassword] = createSignal('')
|
||||
const [validationErrors, setValidationErrors] = createSignal<ValidationErrors>({})
|
||||
// TODO: better solution for interactive error messages
|
||||
const [isEmailNotConfirmed, setIsEmailNotConfirmed] = createSignal(false)
|
||||
|
||||
const [isLinkSent, setIsLinkSent] = createSignal(false)
|
||||
const authFormRef: { current: HTMLFormElement } = { current: null }
|
||||
const { showSnackbar } = useSnackbar()
|
||||
|
@ -52,43 +51,43 @@ export const LoginForm = () => {
|
|||
event.preventDefault()
|
||||
|
||||
setIsLinkSent(true)
|
||||
setIsEmailNotConfirmed(false)
|
||||
setSubmitError('')
|
||||
changeSearchParams({ mode: 'send-reset-link' })
|
||||
// NOTE: temporary solution, needs logic in authorizer
|
||||
/* FIXME:
|
||||
const { authorizer } = useSession()
|
||||
const result = await authorizer().verifyEmail({ token })
|
||||
if (!result) setSubmitError('cant sign send link')
|
||||
*/
|
||||
setSubmitError()
|
||||
changeSearchParams({ mode: 'send-confirm-email' })
|
||||
}
|
||||
|
||||
const preSendValidate = async (value: string, type: 'email' | 'password'): Promise<boolean> => {
|
||||
if (type === 'email') {
|
||||
if (value === '' || !validateEmail(value)) {
|
||||
setValidationErrors((prev) => ({
|
||||
...prev,
|
||||
email: t('Invalid email'),
|
||||
}))
|
||||
return false
|
||||
}
|
||||
} else if (type === 'password') {
|
||||
if (value === '') {
|
||||
setValidationErrors((prev) => ({
|
||||
...prev,
|
||||
password: t('Please enter password'),
|
||||
}))
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
const handleSubmit = async (event: Event) => {
|
||||
event.preventDefault()
|
||||
|
||||
await preSendValidate(email(), 'email')
|
||||
await preSendValidate(password(), 'password')
|
||||
|
||||
setIsLinkSent(false)
|
||||
setIsEmailNotConfirmed(false)
|
||||
setSubmitError('')
|
||||
|
||||
const newValidationErrors: ValidationErrors = {}
|
||||
|
||||
const validateAndSetError = (field, message) => {
|
||||
if (!field()) {
|
||||
newValidationErrors[field.name] = t(message)
|
||||
}
|
||||
}
|
||||
|
||||
validateAndSetError(email, 'Please enter email')
|
||||
validateAndSetError(() => validateEmail(email()), 'Invalid email')
|
||||
validateAndSetError(password, 'Please enter password')
|
||||
|
||||
if (Object.keys(newValidationErrors).length > 0) {
|
||||
setValidationErrors(newValidationErrors)
|
||||
setSubmitError()
|
||||
|
||||
if (Object.keys(validationErrors()).length > 0) {
|
||||
authFormRef.current
|
||||
.querySelector<HTMLInputElement>(`input[name="${Object.keys(newValidationErrors)[0]}"]`)
|
||||
.querySelector<HTMLInputElement>(`input[name="${Object.keys(validationErrors())[0]}"]`)
|
||||
?.focus()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -96,14 +95,27 @@ export const LoginForm = () => {
|
|||
|
||||
try {
|
||||
const { errors } = await signIn({ email: email(), password: password() })
|
||||
console.error('[signIn errors]', errors)
|
||||
if (errors?.length > 0) {
|
||||
if (errors.some((error) => error.message.includes('bad user credentials'))) {
|
||||
setValidationErrors((prev) => ({
|
||||
...prev,
|
||||
password: t('Something went wrong, check email and password'),
|
||||
}))
|
||||
} else if (errors.some((error) => error.message.includes('user not found'))) {
|
||||
setSubmitError('Пользователь не найден')
|
||||
} else if (errors.some((error) => error.message.includes('email not verified'))) {
|
||||
setSubmitError(
|
||||
<div class={styles.info}>
|
||||
{t('This email is not verified')}
|
||||
{'. '}
|
||||
<span class={'link'} onClick={handleSendLinkAgainClick}>
|
||||
{t('Send link again')}
|
||||
</span>
|
||||
</div>,
|
||||
)
|
||||
} else {
|
||||
setSubmitError(t('Error'))
|
||||
setSubmitError(t('Error', errors[0].message))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -121,19 +133,6 @@ export const LoginForm = () => {
|
|||
<form onSubmit={handleSubmit} class={styles.authForm} ref={(el) => (authFormRef.current = el)}>
|
||||
<div>
|
||||
<AuthModalHeader modalType="login" />
|
||||
<Show when={submitError()}>
|
||||
<div class={styles.authInfo}>
|
||||
<div class={styles.warn}>{submitError()}</div>
|
||||
<Show when={isEmailNotConfirmed()}>
|
||||
<span class={'link'} onClick={handleSendLinkAgainClick}>
|
||||
{t('Send link again')}
|
||||
</span>
|
||||
</Show>
|
||||
</div>
|
||||
</Show>
|
||||
<Show when={isLinkSent()}>
|
||||
<div class={styles.authInfo}>{t('Link sent, check your email')}</div>
|
||||
</Show>
|
||||
<div
|
||||
class={clsx('pretty-form__item', {
|
||||
'pretty-form__item--error': validationErrors().email,
|
||||
|
@ -154,11 +153,14 @@ export const LoginForm = () => {
|
|||
</Show>
|
||||
</div>
|
||||
|
||||
<PasswordField variant={'login'} onInput={(value) => handlePasswordInput(value)} />
|
||||
<Show when={validationErrors().password}>
|
||||
<div class={styles.validationError} style={{ position: 'static', 'font-size': '1.4rem' }}>
|
||||
{validationErrors().password}
|
||||
</div>
|
||||
<PasswordField
|
||||
variant={'login'}
|
||||
setError={validationErrors().password}
|
||||
onInput={(value) => handlePasswordInput(value)}
|
||||
/>
|
||||
|
||||
<Show when={submitError()}>
|
||||
<div class={clsx('form-message--error', styles.submitError)}>{submitError()}</div>
|
||||
</Show>
|
||||
|
||||
<div>
|
||||
|
@ -175,7 +177,7 @@ export const LoginForm = () => {
|
|||
})
|
||||
}
|
||||
>
|
||||
{t('Set the new password')}
|
||||
{t('Forgot password?')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -31,11 +31,11 @@
|
|||
}
|
||||
|
||||
/* Red/500 */
|
||||
color: #d00820;
|
||||
color: orange;
|
||||
|
||||
a {
|
||||
color: #d00820;
|
||||
border-color: #d00820;
|
||||
color: orange;
|
||||
border-color: orange;
|
||||
|
||||
&:hover {
|
||||
color: var(--default-color-invert);
|
||||
|
|
|
@ -11,21 +11,23 @@ type Props = {
|
|||
disabled?: boolean
|
||||
placeholder?: string
|
||||
errorMessage?: (error: string) => void
|
||||
setError?: string
|
||||
onInput: (value: string) => void
|
||||
onBlur?: (value: string) => void
|
||||
variant?: 'login' | 'registration'
|
||||
disableAutocomplete?: boolean
|
||||
}
|
||||
|
||||
const minLength = 8
|
||||
const hasNumber = /\d/
|
||||
const hasSpecial = /[!#$%&*@^]/
|
||||
|
||||
export const PasswordField = (props: Props) => {
|
||||
const { t } = useLocalize()
|
||||
const [showPassword, setShowPassword] = createSignal(false)
|
||||
const [error, setError] = createSignal<string>()
|
||||
|
||||
const validatePassword = (passwordToCheck) => {
|
||||
const minLength = 8
|
||||
const hasNumber = /\d/
|
||||
const hasSpecial = /[!#$%&*@^]/
|
||||
|
||||
if (passwordToCheck.length < minLength) {
|
||||
return t('Password should be at least 8 characters')
|
||||
}
|
||||
|
@ -35,11 +37,17 @@ export const PasswordField = (props: Props) => {
|
|||
if (!hasSpecial.test(passwordToCheck)) {
|
||||
return t('Password should contain at least one special character: !@#$%^&*')
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
const handleInputChange = (value) => {
|
||||
const handleInputBlur = (value: string) => {
|
||||
if (props.variant === 'login') {
|
||||
return props.onBlur(value)
|
||||
}
|
||||
if (value.length < 1) {
|
||||
return
|
||||
}
|
||||
|
||||
props.onInput(value)
|
||||
const errorValue = validatePassword(value)
|
||||
if (errorValue) {
|
||||
|
@ -58,14 +66,13 @@ export const PasswordField = (props: Props) => {
|
|||
{ defer: true },
|
||||
),
|
||||
)
|
||||
createEffect(() => {
|
||||
setError(props.setError)
|
||||
})
|
||||
|
||||
return (
|
||||
<div class={clsx(styles.PassportField, props.class)}>
|
||||
<div
|
||||
class={clsx('pretty-form__item', {
|
||||
'pretty-form__item--error': error() && props.variant !== 'login',
|
||||
})}
|
||||
>
|
||||
<div class="pretty-form__item">
|
||||
<input
|
||||
id="password"
|
||||
name="password"
|
||||
|
@ -73,7 +80,7 @@ export const PasswordField = (props: Props) => {
|
|||
autocomplete={props.disableAutocomplete ? 'one-time-code' : 'current-password'}
|
||||
type={showPassword() ? 'text' : 'password'}
|
||||
placeholder={props.placeholder || t('Password')}
|
||||
onInput={(event) => handleInputChange(event.currentTarget.value)}
|
||||
onBlur={(event) => handleInputBlur(event.currentTarget.value)}
|
||||
/>
|
||||
<label for="password">{t('Password')}</label>
|
||||
<button
|
||||
|
@ -83,8 +90,14 @@ export const PasswordField = (props: Props) => {
|
|||
>
|
||||
<Icon class={styles.passwordToggleIcon} name={showPassword() ? 'eye-off' : 'eye'} />
|
||||
</button>
|
||||
<Show when={error() && props.variant !== 'login'}>
|
||||
<div class={clsx(styles.registerPassword, styles.validationError)}>{error()}</div>
|
||||
<Show when={error()}>
|
||||
<div
|
||||
class={clsx(styles.registerPassword, styles.validationError, {
|
||||
'form-message--error': props.setError,
|
||||
})}
|
||||
>
|
||||
{error()}
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -28,10 +28,6 @@ type FormFields = {
|
|||
|
||||
type ValidationErrors = Partial<Record<keyof FormFields, string | JSX.Element>>
|
||||
|
||||
const handleEmailInput = (newEmail: string) => {
|
||||
setEmail(newEmail.toLowerCase())
|
||||
}
|
||||
|
||||
export const RegisterForm = () => {
|
||||
const { changeSearchParams } = useRouter<AuthModalSearchParams>()
|
||||
const { t } = useLocalize()
|
||||
|
@ -52,6 +48,7 @@ export const RegisterForm = () => {
|
|||
}
|
||||
|
||||
const handleSubmit = async (event: Event) => {
|
||||
console.log('!!! handleSubmit:', handleSubmit)
|
||||
event.preventDefault()
|
||||
if (passwordError()) {
|
||||
setValidationErrors((errors) => ({ ...errors, password: passwordError() }))
|
||||
|
@ -137,7 +134,8 @@ export const RegisterForm = () => {
|
|||
setValidationErrors((prev) => ({
|
||||
email: (
|
||||
<>
|
||||
{t('This email is verified')}. {t('You can')}
|
||||
{t('This email is registered')}. {t('try')}
|
||||
{', '}
|
||||
<span class="link" onClick={() => changeSearchParams({ mode: 'login' })}>
|
||||
{t('enter')}
|
||||
</span>
|
||||
|
@ -172,17 +170,18 @@ export const RegisterForm = () => {
|
|||
}
|
||||
}
|
||||
|
||||
const handleEmailInput = (newEmail: string) => {
|
||||
setEmailStatus('')
|
||||
setValidationErrors({})
|
||||
setEmail(newEmail.toLowerCase())
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Show when={!isSuccess()}>
|
||||
<form onSubmit={handleSubmit} class={styles.authForm} ref={(el) => (authFormRef.current = el)}>
|
||||
<div>
|
||||
<AuthModalHeader modalType="register" />
|
||||
<Show when={submitError()}>
|
||||
<div class={styles.authInfo}>
|
||||
<div class={styles.warn}>{submitError()}</div>
|
||||
</div>
|
||||
</Show>
|
||||
<div
|
||||
class={clsx('pretty-form__item', {
|
||||
'pretty-form__item--error': validationErrors().fullName,
|
||||
|
@ -217,9 +216,11 @@ export const RegisterForm = () => {
|
|||
onBlur={handleEmailBlur}
|
||||
/>
|
||||
<label for="email">{t('Email')}</label>
|
||||
<div class={clsx(styles.validationError, { info: Boolean(emailStatus()) })}>
|
||||
{validationErrors().email}
|
||||
</div>
|
||||
<Show when={validationErrors().email || emailStatus()}>
|
||||
<div class={clsx(styles.validationError, { info: Boolean(emailStatus()) })}>
|
||||
{validationErrors().email}
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
<PasswordField
|
||||
|
@ -259,12 +260,14 @@ export const RegisterForm = () => {
|
|||
</form>
|
||||
</Show>
|
||||
<Show when={isSuccess()}>
|
||||
<div class={styles.title}>{t('Almost done! Check your email.')}</div>
|
||||
<div class={styles.text}>{t("We've sent you a message with a link to enter our website.")}</div>
|
||||
<div>
|
||||
<button class={clsx('button', styles.submitButton)} onClick={() => hideModal()}>
|
||||
{t('Back to main page')}
|
||||
</button>
|
||||
<div style={{ 'justify-content': 'center' }}>
|
||||
<div class={styles.title}>{t('Almost done! Check your email.')}</div>
|
||||
<div class={styles.text}>{t("We've sent you a message with a link to enter our website.")}</div>
|
||||
<div>
|
||||
<button class={clsx('button', styles.submitButton)} onClick={() => hideModal()}>
|
||||
{t('Back to main page')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
</>
|
||||
|
|
24
src/components/Nav/AuthModal/SendEmailConfirm.tsx
Normal file
24
src/components/Nav/AuthModal/SendEmailConfirm.tsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { clsx } from 'clsx'
|
||||
import { useLocalize } from '../../../context/localize'
|
||||
import { hideModal } from '../../../stores/ui'
|
||||
|
||||
import styles from './AuthModal.module.scss'
|
||||
|
||||
export const SendEmailConfirm = () => {
|
||||
const { t } = useLocalize()
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
'align-items': 'center',
|
||||
'justify-content': 'center',
|
||||
}}
|
||||
>
|
||||
<div class={styles.text}>{t('Link sent, check your email')}</div>
|
||||
<div>
|
||||
<button class={clsx('button', styles.submitButton)} onClick={() => hideModal()}>
|
||||
{t('Go to main page')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -79,8 +79,12 @@ export const SendResetLinkForm = () => {
|
|||
ref={(el) => (authFormRef.current = el)}
|
||||
>
|
||||
<div>
|
||||
<h4>{t('Set the new password')}</h4>
|
||||
<div class={styles.authSubtitle}>{t(message()) || t('Please give us your email address')}</div>
|
||||
<h4>{t('Forgot password?')}</h4>
|
||||
<Show when={!message()}>
|
||||
<div class={styles.authSubtitle}>
|
||||
{t("It's OK. Just enter your email to receive a link to change your password")}
|
||||
</div>
|
||||
</Show>
|
||||
<div
|
||||
class={clsx('pretty-form__item', {
|
||||
'pretty-form__item--error': validationErrors().email,
|
||||
|
@ -104,7 +108,7 @@ export const SendResetLinkForm = () => {
|
|||
class={'link'}
|
||||
onClick={() =>
|
||||
changeSearchParams({
|
||||
mode: 'login',
|
||||
mode: 'register',
|
||||
})
|
||||
}
|
||||
>
|
||||
|
@ -116,28 +120,31 @@ export const SendResetLinkForm = () => {
|
|||
<div class={styles.validationError}>{validationErrors().email}</div>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
<div style={{ 'margin-top': '5rem' }}>
|
||||
<button
|
||||
class={clsx('button', styles.submitButton)}
|
||||
disabled={isSubmitting() || Boolean(message())}
|
||||
type="submit"
|
||||
>
|
||||
{isSubmitting() ? '...' : t('Send')}
|
||||
</button>
|
||||
</div>
|
||||
<div class={styles.authControl}>
|
||||
<span
|
||||
class={styles.authLink}
|
||||
onClick={() =>
|
||||
changeSearchParams({
|
||||
mode: 'login',
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('I know the password')}
|
||||
</span>
|
||||
</div>
|
||||
<Show when={!message()} fallback={<div class={styles.authSubtitle}>{t(message())}</div>}>
|
||||
<>
|
||||
<div style={{ 'margin-top': '5rem' }}>
|
||||
<button
|
||||
class={clsx('button', styles.submitButton)}
|
||||
disabled={isSubmitting() || Boolean(message())}
|
||||
type="submit"
|
||||
>
|
||||
{isSubmitting() ? '...' : t('Restore password')}
|
||||
</button>
|
||||
</div>
|
||||
<div class={styles.authControl}>
|
||||
<span
|
||||
class={styles.authLink}
|
||||
onClick={() =>
|
||||
changeSearchParams({
|
||||
mode: 'login',
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('I know the password')}
|
||||
</span>
|
||||
</div>
|
||||
</>
|
||||
</Show>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { For } from 'solid-js'
|
||||
|
||||
import { useLocalize } from '../../../context/localize'
|
||||
import { useSession } from '../../../context/session'
|
||||
import { Icon } from '../../_shared/Icon'
|
||||
import { useLocalize } from '../../../../context/localize'
|
||||
import { useSession } from '../../../../context/session'
|
||||
import { Icon } from '../../../_shared/Icon'
|
||||
|
||||
import styles from './SocialProviders.module.scss'
|
||||
|
||||
|
@ -18,7 +18,7 @@ export const SocialProviders = () => {
|
|||
<div class={styles.social}>
|
||||
<For each={PROVIDERS}>
|
||||
{(provider) => (
|
||||
<button class={styles[provider]} onClick={(_e) => oauth(provider)}>
|
||||
<button type="button" class={styles[provider]} onClick={(_e) => oauth(provider)}>
|
||||
<Icon name={provider} />
|
||||
</button>
|
||||
)}
|
1
src/components/Nav/AuthModal/SocialProviders/index.ts
Normal file
1
src/components/Nav/AuthModal/SocialProviders/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export { SocialProviders } from './SocialProviders'
|
|
@ -16,12 +16,14 @@ import { RegisterForm } from './RegisterForm'
|
|||
import { SendResetLinkForm } from './SendResetLinkForm'
|
||||
|
||||
import styles from './AuthModal.module.scss'
|
||||
import { SendEmailConfirm } from './SendEmailConfirm'
|
||||
|
||||
const AUTH_MODAL_MODES: Record<AuthModalMode, Component> = {
|
||||
login: LoginForm,
|
||||
register: RegisterForm,
|
||||
'send-reset-link': SendResetLinkForm,
|
||||
'confirm-email': EmailConfirm,
|
||||
'send-confirm-email': SendEmailConfirm,
|
||||
'change-password': ChangePasswordForm,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
export type AuthModalMode = 'login' | 'register' | 'confirm-email' | 'send-reset-link' | 'change-password'
|
||||
export type AuthModalMode =
|
||||
| 'login'
|
||||
| 'register'
|
||||
| 'confirm-email'
|
||||
| 'send-confirm-email'
|
||||
| 'send-reset-link'
|
||||
| 'change-password'
|
||||
export type AuthModalSource =
|
||||
| 'discussions'
|
||||
| 'vote'
|
||||
|
|
|
@ -464,7 +464,7 @@ form {
|
|||
}
|
||||
|
||||
.form-message--error {
|
||||
color: #d00820;
|
||||
color: var(--danger-color) !important;
|
||||
}
|
||||
|
||||
select {
|
||||
|
|
Loading…
Reference in New Issue
Block a user