mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-10 02:54:15 +00:00
improve login component
This commit is contained in:
parent
ee0c7c4a2d
commit
255e6968c0
@ -7,85 +7,85 @@ import config from "config"
|
|||||||
|
|
||||||
import "./index.less"
|
import "./index.less"
|
||||||
|
|
||||||
const formInstance = [
|
const LoginSteps = {
|
||||||
{
|
"username": (props) => {
|
||||||
id: "username",
|
const handleUpdate = (e) => {
|
||||||
element: {
|
props.onUpdate(e.target.value)
|
||||||
component: "Input",
|
|
||||||
icon: "User",
|
|
||||||
placeholder: "Username",
|
|
||||||
props: {
|
|
||||||
autoCorrect: "off",
|
|
||||||
autoCapitalize: "none",
|
|
||||||
className: "login-form-username",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
item: {
|
|
||||||
hasFeedback: true,
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: 'Please input your Username!',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return <div className="field">
|
||||||
|
<span><Icons.Mail /> Username or Email</span>
|
||||||
|
|
||||||
|
<div className="component">
|
||||||
|
<antd.Input
|
||||||
|
name="username"
|
||||||
|
defaultValue={props.defaultValue}
|
||||||
|
placeholder="myusername / myemail@example.com"
|
||||||
|
onChange={handleUpdate}
|
||||||
|
onPressEnter={props.next}
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="none"
|
||||||
|
autoComplete="on"
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
},
|
},
|
||||||
{
|
"password": (props) => {
|
||||||
id: "password",
|
const handleUpdate = (e) => {
|
||||||
element: {
|
props.onUpdate(e.target.value)
|
||||||
component: "Input",
|
|
||||||
icon: "Lock",
|
|
||||||
placeholder: "Password",
|
|
||||||
props: {
|
|
||||||
type: "password"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
item: {
|
|
||||||
hasFeedback: true,
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: 'Please input your Password!',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
return <div className="field">
|
||||||
id: "login_btn",
|
<span><Icons.Lock /> Password</span>
|
||||||
withValidation: true,
|
|
||||||
element: {
|
<div className="component">
|
||||||
component: "Button",
|
<antd.Input.Password
|
||||||
props: {
|
name="password"
|
||||||
icon: "User",
|
defaultValue={props.defaultValue}
|
||||||
children: "Login",
|
onChange={handleUpdate}
|
||||||
type: "primary",
|
onPressEnter={props.next}
|
||||||
htmlType: "submit"
|
autoCorrect="off"
|
||||||
}
|
autoCapitalize="none"
|
||||||
}
|
autoComplete="on"
|
||||||
},
|
autoFocus
|
||||||
]
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const phasesToSteps = {
|
||||||
|
0: "username",
|
||||||
|
1: "password",
|
||||||
|
}
|
||||||
|
|
||||||
export default class Login extends React.Component {
|
export default class Login extends React.Component {
|
||||||
static pageStatement = {
|
static pageStatement = {
|
||||||
bottomBarAllowed: false
|
bottomBarAllowed: false
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFinish = async (values, ctx) => {
|
state = {
|
||||||
ctx.toogleValidation(true)
|
loading: false,
|
||||||
|
loginInputs: {},
|
||||||
|
error: null,
|
||||||
|
phase: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleFinish = async () => {
|
||||||
const payload = {
|
const payload = {
|
||||||
username: values.username,
|
username: this.state.loginInputs.username,
|
||||||
password: values.password,
|
password: this.state.loginInputs.password,
|
||||||
allowRegenerate: values.allowRegenerate,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.clearError()
|
||||||
|
this.toogleLoading(true)
|
||||||
|
|
||||||
this.props.sessionController.login(payload, (error, response) => {
|
this.props.sessionController.login(payload, (error, response) => {
|
||||||
ctx.toogleValidation(false)
|
this.toogleLoading(false)
|
||||||
ctx.clearErrors()
|
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
ctx.shake("all")
|
return this.onError(error)
|
||||||
return ctx.error("result", error)
|
|
||||||
} else {
|
} else {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.onDone()
|
this.onDone()
|
||||||
@ -104,31 +104,129 @@ export default class Login extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toogleLoading = (to) => {
|
||||||
|
if (typeof to === "undefined") {
|
||||||
|
to = !this.state.loading
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
loading: to
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
clearError = () => {
|
||||||
|
this.setState({
|
||||||
|
error: null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onError = (error) => {
|
||||||
|
this.setState({
|
||||||
|
error: error
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onUpdateInput = (input, value) => {
|
||||||
|
this.setState({
|
||||||
|
loginInputs: {
|
||||||
|
...this.state.loginInputs,
|
||||||
|
[input]: value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCurrentInput = () => {
|
||||||
|
const { phase } = this.state
|
||||||
|
|
||||||
|
const step = phasesToSteps[phase]
|
||||||
|
|
||||||
|
return React.createElement(LoginSteps[step], {
|
||||||
|
onUpdate: (...props) => this.onUpdateInput(step, ...props),
|
||||||
|
next: this.nextStep,
|
||||||
|
defaultValue: this.state.loginInputs[step],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
nextStep = () => {
|
||||||
|
const to = this.state.phase + 1
|
||||||
|
|
||||||
|
if (!phasesToSteps[to]) {
|
||||||
|
return this.handleFinish()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
phase: to
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
prevStep = () => {
|
||||||
|
const to = this.state.phase - 1
|
||||||
|
|
||||||
|
if (!phasesToSteps[to]) {
|
||||||
|
console.warn("No step found for phase", to)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
phase: to
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
canNext = () => {
|
||||||
|
if (this.state.loading) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const { phase } = this.state
|
||||||
|
|
||||||
|
const step = phasesToSteps[phase]
|
||||||
|
|
||||||
|
return !!this.state.loginInputs[step]
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div className="login">
|
return <div className="login_wrapper">
|
||||||
<div className="header">
|
<div className="content">
|
||||||
<div className="logo">
|
<h1>
|
||||||
<img src={config.logo?.full} />
|
Sign in
|
||||||
|
</h1>
|
||||||
|
<h3>
|
||||||
|
To continue to {config.app.siteName}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div className="fields">
|
||||||
|
{this.renderCurrentInput()}
|
||||||
|
|
||||||
|
<div className="field">
|
||||||
|
<div className="component-row">
|
||||||
|
{
|
||||||
|
this.state.phase > 0 && <antd.Button
|
||||||
|
onClick={this.prevStep}
|
||||||
|
disabled={this.state.loading}
|
||||||
|
>
|
||||||
|
Back
|
||||||
|
</antd.Button>
|
||||||
|
}
|
||||||
|
<antd.Button
|
||||||
|
onClick={this.nextStep}
|
||||||
|
disabled={!this.canNext() || this.state.loading}
|
||||||
|
loading={this.state.loading}
|
||||||
|
>
|
||||||
|
Continue
|
||||||
|
</antd.Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="field-error">
|
||||||
|
{this.state.error}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="field">
|
||||||
|
<a>You need a account?</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{this.props.session && <div className="session_available">
|
|
||||||
<h3><Icons.AlertCircle /> You already have a valid session.</h3>
|
|
||||||
<div className="session_card">
|
|
||||||
@{this.props.session.username}
|
|
||||||
</div>
|
|
||||||
<antd.Button
|
|
||||||
type="primary"
|
|
||||||
onClick={() => window.app.setLocation(config.app?.mainPath ?? "/home")} >
|
|
||||||
Go to home
|
|
||||||
</antd.Button>
|
|
||||||
</div>}
|
|
||||||
<FormGenerator
|
|
||||||
name="normal_login"
|
|
||||||
renderLoadingIcon
|
|
||||||
className="login-form"
|
|
||||||
items={formInstance}
|
|
||||||
onFinish={this.handleFinish}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,16 +1,22 @@
|
|||||||
.login {
|
.login_wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
> div {
|
width: 100%;
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
width: 15vw;
|
max-width: 200px;
|
||||||
|
|
||||||
|
margin-bottom: 40px;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -18,21 +24,73 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.login-form {
|
h1 {
|
||||||
display: flex;
|
font-family: "Space Grotesk", sans-serif;
|
||||||
flex-direction: column;
|
margin: 0;
|
||||||
align-items: center;
|
}
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-form-username {
|
h3 {
|
||||||
font-size: 20px!important;
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
input {
|
|
||||||
padding: 20px!important;
|
.content {
|
||||||
font-size: 20px!important;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
width: 80%;
|
||||||
|
|
||||||
|
max-width: 600px;
|
||||||
|
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
|
padding: 40px 0;
|
||||||
|
|
||||||
|
border-radius: 12px;
|
||||||
|
|
||||||
|
.fields {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
|
.field {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.component {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.component-row {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-error {
|
||||||
|
color: red;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-input {
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-input-affix-wrapper {
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
.ant-input {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,9 +113,9 @@
|
|||||||
height: fit-content;
|
height: fit-content;
|
||||||
|
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
|
|
||||||
border: 1px solid #e5e5e5;
|
border: 1px solid #e5e5e5;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user