Refactor validation in SignupModal

This commit is contained in:
Justin Edmund 2022-02-28 15:00:32 -08:00
parent 829146f1bd
commit 0e3aacfbb0

View file

@ -9,8 +9,6 @@ import { accountState } from '~utils/accountState'
import Button from '~components/Button' import Button from '~components/Button'
import Fieldset from '~components/Fieldset' import Fieldset from '~components/Fieldset'
import Modal from '~components/Modal'
import Overlay from '~components/Overlay'
import CrossIcon from '~public/icons/Cross.svg' import CrossIcon from '~public/icons/Cross.svg'
import './index.scss' import './index.scss'
@ -28,6 +26,8 @@ interface ErrorMap {
const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
const SignupModal = (props: Props) => { const SignupModal = (props: Props) => {
// TODO: Clear error state on close
// Set up error handling // Set up error handling
const [formValid, setFormValid] = useState(false) const [formValid, setFormValid] = useState(false)
const [errors, setErrors] = useState<ErrorMap>({ const [errors, setErrors] = useState<ErrorMap>({
@ -55,16 +55,19 @@ const SignupModal = (props: Props) => {
.then((response) => { .then((response) => {
if (!response.data.available) { if (!response.data.available) {
newErrors[name] = `This ${name} is already in use` newErrors[name] = `This ${name} is already in use`
setErrors(newErrors)
setFormValid(false)
} else {
setFormValid(true)
} }
setErrors(newErrors)
}, (error) => { }, (error) => {
console.error(error) console.error(error)
}) })
} }
} }
function process(event: React.FormEvent) { // TODO: Refactor this
function register(event: React.FormEvent) {
event.preventDefault() event.preventDefault()
const body = { const body = {
@ -95,31 +98,53 @@ const SignupModal = (props: Props) => {
} }
} }
function validateForm() { function handleNameChange(event: React.ChangeEvent<HTMLInputElement>) {
let valid = true
Object.values(form).forEach(
(input) => input.current?.value.length == 0 && (valid = false)
)
Object.values(errors).forEach(
(error) => error.length > 0 && (valid = false)
)
return valid
}
function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
event.preventDefault() event.preventDefault()
const { name, value } = event.target const fieldName = event.target.name
const value = event.target.value
if (value.length >= 3) {
api.check(fieldName, value)
.then((response) => {
processNameCheck(fieldName, value, response.data.available)
}, (error) => {
console.error(error)
})
} else {
validateName(fieldName, value)
}
}
function processNameCheck(fieldName: string, value: string, available: boolean) {
const newErrors = {...errors}
if (available) {
// Continue checking for errors
newErrors[fieldName] = ''
setErrors(newErrors)
setFormValid(true)
validateName(fieldName, value)
} else {
newErrors[fieldName] = `This ${fieldName} is already in use`
setErrors(newErrors)
setFormValid(false)
}
}
function validateName(fieldName: string, value: string) {
let newErrors = {...errors} let newErrors = {...errors}
switch(name) { switch(fieldName) {
case 'username': case 'username':
newErrors.username = value.length < 3 if (value.length < 3)
? 'Username must be at least 3 characters' newErrors.username = 'Username must be at least 3 characters'
: '' else if (value.length > 20)
newErrors.username = 'Username must be less than 20 characters'
else
newErrors.username = ''
break break
case 'email': case 'email':
@ -128,6 +153,21 @@ const SignupModal = (props: Props) => {
: 'That email address is not valid' : 'That email address is not valid'
break break
default:
break
}
setErrors(newErrors)
setFormValid(validateForm(newErrors))
}
function handlePasswordChange(event: React.ChangeEvent<HTMLInputElement>) {
event.preventDefault()
const { name, value } = event.target
let newErrors = {...errors}
switch(name) {
case 'password': case 'password':
newErrors.password = passwordInput.current?.value.includes(usernameInput.current?.value!) newErrors.password = passwordInput.current?.value.includes(usernameInput.current?.value!)
? 'Your password should not contain your username' ? 'Your password should not contain your username'
@ -151,7 +191,21 @@ const SignupModal = (props: Props) => {
} }
setErrors(newErrors) setErrors(newErrors)
setFormValid(validateForm()) setFormValid(validateForm(newErrors))
}
function validateForm(errors: ErrorMap) {
let valid = true
Object.values(form).forEach(
(input) => input.current?.value.length == 0 && (valid = false)
)
Object.values(errors).forEach(
(error) => error.length > 0 && (valid = false)
)
return valid
} }
return ( return (
@ -174,12 +228,11 @@ const SignupModal = (props: Props) => {
<form className="form" onSubmit={process}> <form className="form" onSubmit={register}>
<Fieldset <Fieldset
fieldName="username" fieldName="username"
placeholder="Username" placeholder="Username"
onBlur={check} onChange={handleNameChange}
onChange={handleChange}
error={errors.username} error={errors.username}
ref={usernameInput} ref={usernameInput}
/> />
@ -188,7 +241,7 @@ const SignupModal = (props: Props) => {
fieldName="email" fieldName="email"
placeholder="Email address" placeholder="Email address"
onBlur={check} onBlur={check}
onChange={handleChange} onChange={handleNameChange}
error={errors.email} error={errors.email}
ref={emailInput} ref={emailInput}
/> />
@ -196,7 +249,7 @@ const SignupModal = (props: Props) => {
<Fieldset <Fieldset
fieldName="password" fieldName="password"
placeholder="Password" placeholder="Password"
onChange={handleChange} onChange={handlePasswordChange}
error={errors.password} error={errors.password}
ref={passwordInput} ref={passwordInput}
/> />
@ -204,7 +257,7 @@ const SignupModal = (props: Props) => {
<Fieldset <Fieldset
fieldName="confirm_password" fieldName="confirm_password"
placeholder="Password (again)" placeholder="Password (again)"
onChange={handleChange} onChange={handlePasswordChange}
error={errors.passwordConfirmation} error={errors.passwordConfirmation}
ref={passwordConfirmationInput} ref={passwordConfirmationInput}
/> />