From 255e6968c07f115ce376474ef8a8ed2dc77d18d6 Mon Sep 17 00:00:00 2001 From: srgooglo Date: Tue, 25 Oct 2022 11:52:32 +0000 Subject: [PATCH] improve login component --- packages/app/src/components/Login/index.jsx | 268 +++++++++++++------ packages/app/src/components/Login/index.less | 98 +++++-- 2 files changed, 261 insertions(+), 105 deletions(-) diff --git a/packages/app/src/components/Login/index.jsx b/packages/app/src/components/Login/index.jsx index b07954e9..0e444175 100755 --- a/packages/app/src/components/Login/index.jsx +++ b/packages/app/src/components/Login/index.jsx @@ -7,85 +7,85 @@ import config from "config" import "./index.less" -const formInstance = [ - { - id: "username", - element: { - 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!', - }, - ], +const LoginSteps = { + "username": (props) => { + const handleUpdate = (e) => { + props.onUpdate(e.target.value) } + + return
+ Username or Email + +
+ +
+
}, - { - id: "password", - element: { - component: "Input", - icon: "Lock", - placeholder: "Password", - props: { - type: "password" - } - }, - item: { - hasFeedback: true, - rules: [ - { - required: true, - message: 'Please input your Password!', - }, - ], + "password": (props) => { + const handleUpdate = (e) => { + props.onUpdate(e.target.value) } - }, - { - id: "login_btn", - withValidation: true, - element: { - component: "Button", - props: { - icon: "User", - children: "Login", - type: "primary", - htmlType: "submit" - } - } - }, -] + + return
+ Password + +
+ +
+
+ } +} + +const phasesToSteps = { + 0: "username", + 1: "password", +} export default class Login extends React.Component { static pageStatement = { bottomBarAllowed: false } - handleFinish = async (values, ctx) => { - ctx.toogleValidation(true) + state = { + loading: false, + loginInputs: {}, + error: null, + phase: 0, + } + handleFinish = async () => { const payload = { - username: values.username, - password: values.password, - allowRegenerate: values.allowRegenerate, + username: this.state.loginInputs.username, + password: this.state.loginInputs.password, } + this.clearError() + this.toogleLoading(true) + this.props.sessionController.login(payload, (error, response) => { - ctx.toogleValidation(false) - ctx.clearErrors() + this.toogleLoading(false) if (error) { - ctx.shake("all") - return ctx.error("result", error) + return this.onError(error) } else { if (response.status === 200) { 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() { - return
-
-
- + return
+
+

+ Sign in +

+

+ To continue to {config.app.siteName} +

+ +
+ {this.renderCurrentInput()} + +
+
+ { + this.state.phase > 0 && + Back + + } + + Continue + +
+
+ +
+ {this.state.error} +
+ +
- {this.props.session &&
-

You already have a valid session.

-
- @{this.props.session.username} -
- window.app.setLocation(config.app?.mainPath ?? "/home")} > - Go to home - -
} -
} } \ No newline at end of file diff --git a/packages/app/src/components/Login/index.less b/packages/app/src/components/Login/index.less index 72063f2b..5fe8093c 100755 --- a/packages/app/src/components/Login/index.less +++ b/packages/app/src/components/Login/index.less @@ -1,16 +1,22 @@ -.login { +.login_wrapper { display: flex; flex-direction: column; + align-items: center; justify-content: center; - > div { - margin-bottom: 20px; - } + width: 100%; .header { + display: flex; + flex-direction: column; + + width: 100%; + .logo { - width: 15vw; + max-width: 200px; + + margin-bottom: 40px; img { width: 100%; @@ -18,21 +24,73 @@ } } } -} -.login-form { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} + h1 { + font-family: "Space Grotesk", sans-serif; + margin: 0; + } -.login-form-username { - font-size: 20px!important; - - input { - padding: 20px!important; - font-size: 20px!important; + h3 { + font-size: 0.8rem; + } + + .content { + 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; margin: 10px; - padding: 5px 10px; + padding: 5px 10px; border: 1px solid #e5e5e5; border-radius: 8px; } -} +} \ No newline at end of file