webapp/src/components/Nav/AuthModal/PasswordField/PasswordField.tsx

104 lines
2.9 KiB
TypeScript
Raw Normal View History

import { clsx } from 'clsx'
2024-02-04 11:25:21 +00:00
import { Show, createEffect, createSignal, on } from 'solid-js'
import { useLocalize } from '../../../../context/localize'
import { Icon } from '../../../_shared/Icon'
import styles from './PasswordField.module.scss'
type Props = {
class?: string
2024-02-06 14:34:27 +00:00
disabled?: boolean
placeholder?: string
errorMessage?: (error: string) => void
setError?: string
2024-03-11 07:41:31 +00:00
onInput?: (value: string) => void
onBlur?: (value: string) => void
2024-01-27 06:21:48 +00:00
variant?: 'login' | 'registration'
2024-02-08 15:37:17 +00:00
disableAutocomplete?: boolean
noValidate?: boolean
onFocus?: () => void
value?: string
}
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: string) => {
if (passwordToCheck.length < minLength) {
return t('Password should be at least 8 characters')
}
if (!hasNumber.test(passwordToCheck)) {
return t('Password should contain at least one number')
}
if (!hasSpecial.test(passwordToCheck)) {
return t('Password should contain at least one special character: !@#$%^&*')
}
return null
}
const handleInputBlur = (value: string) => {
2024-03-11 07:41:31 +00:00
if (props.variant === 'login' && props.onBlur) {
props.onBlur(value)
return
}
if (value.length < 1) {
return
}
2024-06-24 17:50:27 +00:00
props.onInput?.(value)
if (!props.noValidate) {
const errorValue = validatePassword(value)
if (errorValue) {
setError(errorValue)
} else {
setError()
}
}
}
2024-05-20 23:15:52 +00:00
createEffect(on(error, (er) => er && props.errorMessage?.(er), { defer: true }))
createEffect(() => setError(props.setError))
return (
<div class={clsx(styles.PassportField, props.class)}>
<div class="pretty-form__item">
<input
id="password"
name="password"
2024-02-06 14:34:27 +00:00
disabled={props.disabled}
onFocus={props.onFocus}
value={props.value ? props.value : ''}
2024-02-08 15:37:17 +00:00
autocomplete={props.disableAutocomplete ? 'one-time-code' : 'current-password'}
type={showPassword() ? 'text' : 'password'}
2024-02-06 14:34:27 +00:00
placeholder={props.placeholder || t('Password')}
onBlur={(event) => handleInputBlur(event.currentTarget.value)}
/>
<label for="password">{t('Password')}</label>
<button
type="button"
class={styles.passwordToggle}
onClick={() => setShowPassword(!showPassword())}
>
<Icon class={styles.passwordToggleIcon} name={showPassword() ? 'eye-off' : 'eye'} />
</button>
<Show when={error()}>
<div
class={clsx(styles.registerPassword, styles.validationError, {
2024-06-26 08:22:05 +00:00
'form-message--error': props.setError
})}
>
{error()}
</div>
</Show>
</div>
</div>
)
}