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
+ }
+}
+
+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