blessing-skin-server/resources/assets/src/views/auth/Registration.tsx
2020-03-29 23:02:43 +08:00

183 lines
5.5 KiB
TypeScript

import React, { useState, useRef } from 'react'
import { hot } from 'react-hot-loader/root'
import useBlessingExtra from '@/scripts/hooks/useBlessingExtra'
import { t } from '@/scripts/i18n'
import * as fetch from '@/scripts/net'
import { toast } from '@/scripts/notify'
import Alert from '@/components/Alert'
import Captcha from '@/components/Captcha'
const Registration: React.FC = () => {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [confirmation, setConfirmation] = useState('')
const [nickName, setNickName] = useState('')
const [playerName, setPlayerName] = useState('')
const [isPending, setIsPending] = useState(false)
const [warningMessage, setWarningMessage] = useState('')
const requirePlayer = useBlessingExtra<boolean>('player')
const confirmationRef = useRef<HTMLInputElement | null>(null)
const captchaRef = useRef<Captcha | null>(null)
const handleEmailChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setEmail(event.target.value)
}
const handlePasswordChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setPassword(event.target.value)
}
const handleConfirmationChange = (
event: React.ChangeEvent<HTMLInputElement>,
) => {
setConfirmation(event.target.value)
}
const handleNickNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setNickName(event.target.value)
}
const handlePlayerNameChange = (
event: React.ChangeEvent<HTMLInputElement>,
) => {
setPlayerName(event.target.value)
}
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
setWarningMessage('')
if (password !== confirmation) {
setWarningMessage(t('auth.invalidConfirmPwd'))
confirmationRef.current!.focus()
return
}
setIsPending(true)
const { code, message } = await fetch.post<fetch.ResponseBody>(
'/auth/register',
Object.assign(
{ email, password, captcha: await captchaRef.current!.execute() },
requirePlayer ? { player_name: playerName } : { nickname: nickName },
),
)
if (code === 0) {
toast.success(message)
setTimeout(() => {
window.location.href = `${blessing.base_url}/user`
}, 3000)
} else {
setWarningMessage(message)
captchaRef.current!.reset()
}
setIsPending(false)
}
return (
<form onSubmit={handleSubmit}>
<div className="input-group mb-3">
<input
type="email"
required
className="form-control"
placeholder={t('auth.email')}
value={email}
onChange={handleEmailChange}
/>
<div className="input-group-append">
<div className="input-group-text">
<i className="fas fa-envelope"></i>
</div>
</div>
</div>
<div className="input-group mb-3">
<input
type="password"
required
minLength={8}
maxLength={32}
className="form-control"
placeholder={t('auth.password')}
value={password}
onChange={handlePasswordChange}
/>
<div className="input-group-append">
<div className="input-group-text">
<i className="fas fa-lock"></i>
</div>
</div>
</div>
<div className="input-group mb-3">
<input
type="password"
required
minLength={8}
maxLength={32}
className="form-control"
placeholder={t('auth.repeat-pwd')}
ref={confirmationRef}
value={confirmation}
onChange={handleConfirmationChange}
/>
<div className="input-group-append">
<div className="input-group-text">
<i className="fas fa-sign-in-alt"></i>
</div>
</div>
</div>
{requirePlayer ? (
<div className="input-group mb-3" title={t('auth.player-name-intro')}>
<input
type="text"
required
className="form-control"
placeholder={t('auth.player-name')}
value={playerName}
onChange={handlePlayerNameChange}
/>
<div className="input-group-append">
<div className="input-group-text">
<i className="fas fa-gamepad"></i>
</div>
</div>
</div>
) : (
<div className="input-group mb-3" title={t('auth.nickname-intro')}>
<input
type="text"
required
className="form-control"
placeholder={t('auth.nickname')}
value={nickName}
onChange={handleNickNameChange}
/>
<div className="input-group-append">
<div className="input-group-text">
<i className="fas fa-gamepad"></i>
</div>
</div>
</div>
)}
<Captcha ref={captchaRef} />
<Alert type="warning">{warningMessage}</Alert>
<div className="d-flex justify-content-between align-items-center mb-3">
<a href={`${blessing.base_url}/auth/login`}>{t('auth.login-link')}</a>
<button className="btn btn-primary" type="submit" disabled={isPending}>
{isPending ? (
<>
<i className="fas fa-spinner fa-spin mr-1"></i>
{t('auth.registering')}
</>
) : (
t('auth.register-button')
)}
</button>
</div>
</form>
)
}
export default hot(Registration)