mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 18:44:16 +00:00
format
This commit is contained in:
parent
9c057d6017
commit
b395a5f062
@ -8,362 +8,415 @@ import { Icons } from "@components/Icons"
|
|||||||
import "./index.less"
|
import "./index.less"
|
||||||
|
|
||||||
const steps = [
|
const steps = [
|
||||||
{
|
{
|
||||||
key: "username",
|
key: "username",
|
||||||
title: "Step 1",
|
title: "Step 1",
|
||||||
icon: "FiUser",
|
icon: "FiUser",
|
||||||
description: () => <div>
|
description: () => (
|
||||||
<p>Enter your username you gonna use for your account, its used to access to your account.</p>
|
<div>
|
||||||
<p>It must be unique, on lower case, and contain only accepted characters as letters, numbers, underscores.</p>
|
<p>
|
||||||
</div>,
|
Enter your username you gonna use for your account, its used
|
||||||
required: true,
|
to access to your account.
|
||||||
content: (props) => {
|
</p>
|
||||||
const [loading, setLoading] = React.useState(false)
|
<p>
|
||||||
const [username, setUsername] = React.useState("")
|
It must be unique, on lower case, and contain only accepted
|
||||||
const [validCharacters, setValidCharacters] = React.useState(null)
|
characters as letters, numbers, underscores.
|
||||||
const [usernameAvailable, setUsernameAvailable] = React.useState(null)
|
</p>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
required: true,
|
||||||
|
content: (props) => {
|
||||||
|
const [loading, setLoading] = React.useState(false)
|
||||||
|
const [username, setUsername] = React.useState("")
|
||||||
|
const [validCharacters, setValidCharacters] = React.useState(null)
|
||||||
|
const [usernameAvailable, setUsernameAvailable] =
|
||||||
|
React.useState(null)
|
||||||
|
|
||||||
const isValid = () => {
|
const isValid = () => {
|
||||||
return username.length > 0 && validCharacters && usernameAvailable
|
return (
|
||||||
}
|
username.length > 0 && validCharacters && usernameAvailable
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const hasValidCharacters = (username) => {
|
const hasValidCharacters = (username) => {
|
||||||
return /^[a-z0-9_]+$/.test(username)
|
return /^[a-z0-9_]+$/.test(username)
|
||||||
}
|
}
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
if (!isValid()) return
|
if (!isValid()) return
|
||||||
|
|
||||||
props.onPressEnter()
|
props.onPressEnter()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleUpdate = (e) => {
|
const handleUpdate = (e) => {
|
||||||
if (e.target.value === " ") {
|
if (e.target.value === " ") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
e.target.value = e.target.value.toLowerCase()
|
e.target.value = e.target.value.toLowerCase()
|
||||||
|
|
||||||
setUsername(e.target.value)
|
setUsername(e.target.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderIndicator = (value, label) => {
|
const renderIndicator = (value, label) => {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <>
|
return (
|
||||||
<Icons.LoadingOutlined />
|
<>
|
||||||
<p>{label}</p>
|
<Icons.LoadingOutlined />
|
||||||
</>
|
<p>{label}</p>
|
||||||
}
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
return <>
|
return (
|
||||||
<Icons.CheckCircleOutlined />
|
<>
|
||||||
<p>{label}</p>
|
<Icons.CheckCircleOutlined />
|
||||||
</>
|
<p>{label}</p>
|
||||||
}
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return <>
|
return (
|
||||||
<Icons.CloseCircleOutlined />
|
<>
|
||||||
<p>{label}</p>
|
<Icons.CloseCircleOutlined />
|
||||||
</>
|
<p>{label}</p>
|
||||||
}
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (username.length === 0) {
|
if (username.length === 0) {
|
||||||
setUsernameAvailable(null)
|
setUsernameAvailable(null)
|
||||||
setValidCharacters(null)
|
setValidCharacters(null)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
props.handleUpdate(null)
|
props.handleUpdate(null)
|
||||||
|
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
|
|
||||||
setValidCharacters(hasValidCharacters(username))
|
setValidCharacters(hasValidCharacters(username))
|
||||||
|
|
||||||
const timer = setTimeout(async () => {
|
const timer = setTimeout(async () => {
|
||||||
if (!validCharacters) {
|
if (!validCharacters) {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const request = await AuthModel.availability({ username }).catch((error) => {
|
const request = await AuthModel.availability({
|
||||||
antd.message.error(`Cannot check username availability: ${error.message}`)
|
username,
|
||||||
console.error(error)
|
}).catch((error) => {
|
||||||
|
antd.message.error(
|
||||||
|
`Cannot check username availability: ${error.message}`,
|
||||||
|
)
|
||||||
|
console.error(error)
|
||||||
|
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
if (request) {
|
if (request) {
|
||||||
setUsernameAvailable(request.available)
|
setUsernameAvailable(request.available)
|
||||||
|
|
||||||
if (!request.available) {
|
if (!request.available) {
|
||||||
props.handleUpdate(null)
|
props.handleUpdate(null)
|
||||||
} else {
|
} else {
|
||||||
props.handleUpdate(username)
|
props.handleUpdate(username)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
return () => clearTimeout(timer)
|
return () => clearTimeout(timer)
|
||||||
}, [username])
|
}, [username])
|
||||||
|
|
||||||
return <div className="steps step content">
|
return (
|
||||||
<antd.Input
|
<div className="steps step content">
|
||||||
autoCorrect="off"
|
<antd.Input
|
||||||
autoCapitalize="none"
|
autoCorrect="off"
|
||||||
onPressEnter={submit}
|
autoCapitalize="none"
|
||||||
placeholder="newuser"
|
onPressEnter={submit}
|
||||||
value={username}
|
placeholder="newuser"
|
||||||
onChange={handleUpdate}
|
value={username}
|
||||||
status={username.length == 0 ? "default" : loading ? "default" : (isValid() ? "success" : "error")}
|
onChange={handleUpdate}
|
||||||
/>
|
status={
|
||||||
|
username.length == 0
|
||||||
|
? "default"
|
||||||
|
: loading
|
||||||
|
? "default"
|
||||||
|
: isValid()
|
||||||
|
? "success"
|
||||||
|
: "error"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="usernameValidity">
|
<div className="usernameValidity">
|
||||||
<div className="check">
|
<div className="check">
|
||||||
{
|
{renderIndicator(
|
||||||
renderIndicator(usernameAvailable, "Username available")
|
usernameAvailable,
|
||||||
}
|
"Username available",
|
||||||
</div>
|
)}
|
||||||
<div className="check">
|
</div>
|
||||||
{
|
<div className="check">
|
||||||
renderIndicator(validCharacters, "Valid characters (letters, numbers, underscores)")
|
{renderIndicator(
|
||||||
}
|
validCharacters,
|
||||||
</div>
|
"Valid characters (letters, numbers, underscores)",
|
||||||
</div>
|
)}
|
||||||
</div>
|
</div>
|
||||||
},
|
</div>
|
||||||
},
|
</div>
|
||||||
{
|
)
|
||||||
key: "password",
|
},
|
||||||
title: "Step 2",
|
},
|
||||||
icon: "FiKey",
|
{
|
||||||
description: "Enter a password for the account. must comply with the password requirements policy.",
|
key: "password",
|
||||||
required: true,
|
title: "Step 2",
|
||||||
content: (props) => {
|
icon: "FiKey",
|
||||||
const confirmRef = React.useRef(null)
|
description:
|
||||||
|
"Enter a password for the account. must comply with the password requirements policy.",
|
||||||
|
required: true,
|
||||||
|
content: (props) => {
|
||||||
|
const confirmRef = React.useRef(null)
|
||||||
|
|
||||||
const [password, setPassword] = React.useState("")
|
const [password, setPassword] = React.useState("")
|
||||||
const [confirmedPassword, setConfirmedPassword] = React.useState("")
|
const [confirmedPassword, setConfirmedPassword] = React.useState("")
|
||||||
const [passwordStrength, setPasswordStrength] = React.useState(null)
|
const [passwordStrength, setPasswordStrength] = React.useState(null)
|
||||||
|
|
||||||
const passwordMinimunStrength = 3
|
const passwordMinimunStrength = 3
|
||||||
const passwordsMatch = password === confirmedPassword
|
const passwordsMatch = password === confirmedPassword
|
||||||
const passwordError = !passwordsMatch && confirmedPassword.length > 0
|
const passwordError =
|
||||||
|
!passwordsMatch && confirmedPassword.length > 0
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
if (!passwordError) {
|
if (!passwordError) {
|
||||||
props.onPressEnter()
|
props.onPressEnter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const passwordStrengthCalculator = (password) => {
|
const passwordStrengthCalculator = (password) => {
|
||||||
let strength = 0
|
let strength = 0
|
||||||
|
|
||||||
if (password.length === 0 || password.length < 8) {
|
if (password.length === 0 || password.length < 8) {
|
||||||
return strength
|
return strength
|
||||||
}
|
}
|
||||||
|
|
||||||
strength += 1
|
strength += 1
|
||||||
|
|
||||||
if (password.length >= 12) {
|
if (password.length >= 12) {
|
||||||
strength += 1
|
strength += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password.match(/[a-z]/)) {
|
if (password.match(/[a-z]/)) {
|
||||||
strength += 1
|
strength += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password.match(/[A-Z]/)) {
|
if (password.match(/[A-Z]/)) {
|
||||||
strength += 1
|
strength += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password.match(/[0-9]/)) {
|
if (password.match(/[0-9]/)) {
|
||||||
strength += 1
|
strength += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password.match(/[^a-zA-Z0-9]/)) {
|
if (password.match(/[^a-zA-Z0-9]/)) {
|
||||||
strength += 1
|
strength += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return strength
|
return strength
|
||||||
}
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const calculatedStrength = passwordStrengthCalculator(password)
|
const calculatedStrength = passwordStrengthCalculator(password)
|
||||||
|
|
||||||
setPasswordStrength(calculatedStrength)
|
setPasswordStrength(calculatedStrength)
|
||||||
|
|
||||||
if (password !== confirmedPassword) {
|
if (password !== confirmedPassword) {
|
||||||
props.handleUpdate(null)
|
props.handleUpdate(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (calculatedStrength < passwordMinimunStrength) {
|
if (calculatedStrength < passwordMinimunStrength) {
|
||||||
props.handleUpdate(null)
|
props.handleUpdate(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (calculatedStrength >= passwordMinimunStrength && password === confirmedPassword) {
|
if (
|
||||||
props.handleUpdate(password)
|
calculatedStrength >= passwordMinimunStrength &&
|
||||||
}
|
password === confirmedPassword
|
||||||
}, [password, confirmedPassword])
|
) {
|
||||||
|
props.handleUpdate(password)
|
||||||
|
}
|
||||||
|
}, [password, confirmedPassword])
|
||||||
|
|
||||||
return <div className="steps step content passwordsInput">
|
return (
|
||||||
<antd.Input.Password
|
<div className="steps step content passwordsInput">
|
||||||
className="password"
|
<antd.Input.Password
|
||||||
placeholder="Password"
|
className="password"
|
||||||
autoCorrect="off"
|
placeholder="Password"
|
||||||
autoCapitalize="none"
|
autoCorrect="off"
|
||||||
onPressEnter={() => {
|
autoCapitalize="none"
|
||||||
confirmRef.current.focus()
|
onPressEnter={() => {
|
||||||
}}
|
confirmRef.current.focus()
|
||||||
onChange={(e) => {
|
}}
|
||||||
setPassword(e.target.value)
|
onChange={(e) => {
|
||||||
}}
|
setPassword(e.target.value)
|
||||||
status={passwordError ? "error" : "success"}
|
}}
|
||||||
autoFocus
|
status={passwordError ? "error" : "success"}
|
||||||
/>
|
autoFocus
|
||||||
|
/>
|
||||||
|
|
||||||
<antd.Input.Password
|
<antd.Input.Password
|
||||||
className="password"
|
className="password"
|
||||||
placeholder="Confirm Password"
|
placeholder="Confirm Password"
|
||||||
ref={confirmRef}
|
ref={confirmRef}
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
onPressEnter={submit}
|
onPressEnter={submit}
|
||||||
status={passwordError ? "error" : "success"}
|
status={passwordError ? "error" : "success"}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setConfirmedPassword(e.target.value)
|
setConfirmedPassword(e.target.value)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<antd.Progress
|
<antd.Progress
|
||||||
percent={passwordStrength * 20}
|
percent={passwordStrength * 20}
|
||||||
status={passwordStrength < passwordMinimunStrength ? "exception" : "success"}
|
status={
|
||||||
showInfo={false}
|
passwordStrength < passwordMinimunStrength
|
||||||
/>
|
? "exception"
|
||||||
|
: "success"
|
||||||
|
}
|
||||||
|
showInfo={false}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="passwordPolicy">
|
<div className="passwordPolicy">
|
||||||
<p>Password must be at least 8 characters long.</p>
|
<p>Password must be at least 8 characters long.</p>
|
||||||
<p>Password must contain at least one number.</p>
|
<p>Password must contain at least one number.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
},
|
)
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
key: "email",
|
{
|
||||||
title: "Step 3",
|
key: "email",
|
||||||
icon: "FiMail",
|
title: "Step 3",
|
||||||
description: "Enter a email for the account",
|
icon: "FiMail",
|
||||||
required: true,
|
description: "Enter a email for the account",
|
||||||
content: (props) => {
|
required: true,
|
||||||
const [email, setEmail] = React.useState("")
|
content: (props) => {
|
||||||
|
const [email, setEmail] = React.useState("")
|
||||||
|
|
||||||
const [loading, setLoading] = React.useState(false)
|
const [loading, setLoading] = React.useState(false)
|
||||||
const [validFormat, setValidFormat] = React.useState(null)
|
const [validFormat, setValidFormat] = React.useState(null)
|
||||||
const [emailAvailable, setEmailAvailable] = React.useState(null)
|
const [emailAvailable, setEmailAvailable] = React.useState(null)
|
||||||
|
|
||||||
const isValid = () => {
|
const isValid = () => {
|
||||||
return email.length > 0 && validFormat && emailAvailable
|
return email.length > 0 && validFormat && emailAvailable
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkIfIsEmail = (email) => {
|
const checkIfIsEmail = (email) => {
|
||||||
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
|
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
|
||||||
}
|
}
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
if (!isValid()) return
|
if (!isValid()) return
|
||||||
|
|
||||||
props.onPressEnter()
|
props.onPressEnter()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleUpdate = (e) => {
|
const handleUpdate = (e) => {
|
||||||
setEmail(e.target.value)
|
setEmail(e.target.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (email.length === 0) {
|
if (email.length === 0) {
|
||||||
setEmailAvailable(null)
|
setEmailAvailable(null)
|
||||||
setValidFormat(null)
|
setValidFormat(null)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
props.handleUpdate(null)
|
props.handleUpdate(null)
|
||||||
|
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
|
|
||||||
setValidFormat(checkIfIsEmail(email))
|
setValidFormat(checkIfIsEmail(email))
|
||||||
|
|
||||||
// check if email is available
|
// check if email is available
|
||||||
const timer = setTimeout(async () => {
|
const timer = setTimeout(async () => {
|
||||||
if (!validFormat) return
|
if (!validFormat) return
|
||||||
|
|
||||||
const request = await AuthModel.availability({ email }).catch((error) => {
|
const request = await AuthModel.availability({
|
||||||
antd.message.error(`Cannot check email availability: ${error.message}`)
|
email,
|
||||||
|
}).catch((error) => {
|
||||||
|
antd.message.error(
|
||||||
|
`Cannot check email availability: ${error.message}`,
|
||||||
|
)
|
||||||
|
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
if (request) {
|
if (request) {
|
||||||
setEmailAvailable(request.available)
|
setEmailAvailable(request.available)
|
||||||
|
|
||||||
if (!request.available) {
|
if (!request.available) {
|
||||||
antd.message.error("Email is already in use")
|
antd.message.error("Email is already in use")
|
||||||
props.handleUpdate(null)
|
props.handleUpdate(null)
|
||||||
} else {
|
} else {
|
||||||
props.handleUpdate(email)
|
props.handleUpdate(email)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
return () => clearTimeout(timer)
|
return () => clearTimeout(timer)
|
||||||
}, [email])
|
}, [email])
|
||||||
|
|
||||||
return <div className="steps step content">
|
return (
|
||||||
<antd.Input
|
<div className="steps step content">
|
||||||
placeholder="Email"
|
<antd.Input
|
||||||
onPressEnter={submit}
|
placeholder="Email"
|
||||||
onChange={handleUpdate}
|
onPressEnter={submit}
|
||||||
status={email.length == 0 ? "default" : loading ? "default" : (isValid() ? "success" : "error")}
|
onChange={handleUpdate}
|
||||||
/>
|
status={
|
||||||
</div>
|
email.length == 0
|
||||||
},
|
? "default"
|
||||||
},
|
: loading
|
||||||
|
? "default"
|
||||||
|
: isValid()
|
||||||
|
? "success"
|
||||||
|
: "error"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export default (props) => {
|
export default (props) => {
|
||||||
const onSubmit = async (values) => {
|
const onSubmit = async (values) => {
|
||||||
const result = await AuthModel.register(values).catch((error) => {
|
const result = await AuthModel.register(values).catch((error) => {
|
||||||
throw new Error(`Failed to register user: ${error.message}`)
|
throw new Error(`Failed to register user: ${error.message}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
antd.message.success("User registered successfully.")
|
antd.message.success("User registered successfully.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.locked) {
|
if (props.locked) {
|
||||||
props.unlock()
|
props.unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof props.close === "function") {
|
if (typeof props.close === "function") {
|
||||||
props.close()
|
props.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app.isMobile) {
|
if (app.isMobile) {
|
||||||
app.controls.openLoginForm({
|
app.auth.login()
|
||||||
defaultLocked: props.locked,
|
}
|
||||||
})
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return <StepsForm
|
return <StepsForm steps={steps} onSubmit={onSubmit} />
|
||||||
steps={steps}
|
|
||||||
onSubmit={onSubmit}
|
|
||||||
/>
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user