sprinklers3/client/pages/LoginPage.tsx

83 lines
2.6 KiB
TypeScript

import { computed, observable } from "mobx";
import { observer } from "mobx-react";
import * as React from "react";
import { Container, Dimmer, Form, Header, InputOnChangeData, Loader, Message, Segment } from "semantic-ui-react";
import { AppState, injectState } from "@client/state";
import log from "@common/logger";
import "@client/styles/LoginPage";
class LoginPageState {
@observable username = "";
@observable password = "";
@observable loading: boolean = false;
@observable error: string | null = null;
@computed get canLogin() {
return this.username.length > 0 && this.password.length > 0;
}
onUsernameChange = (e: any, data: InputOnChangeData) => {
this.username = data.value;
}
onPasswordChange = (e: any, data: InputOnChangeData) => {
this.password = data.value;
}
login(appState: AppState) {
this.loading = true;
this.error = null;
appState.tokenStore.grantPassword(this.username, this.password)
.then(() => {
this.loading = false;
log.info("logged in");
appState.history.push("/");
})
.catch((err) => {
this.loading = false;
this.error = err.message;
log.error({ err }, "login error");
});
}
}
class LoginPage extends React.Component<{ appState: AppState }> {
pageState = new LoginPageState();
render() {
const { username, password, canLogin, loading, error } = this.pageState;
return (
<Container className="loginPage">
<Segment>
<Dimmer inverted active={loading}>
<Loader/>
</Dimmer>
<Header as="h1">Login</Header>
<Form>
<Form.Input label="Username" value={username} onChange={this.pageState.onUsernameChange}/>
<Form.Input
label="Password"
value={password}
type="password"
onChange={this.pageState.onPasswordChange}
/>
<Message error visible={error != null}>{error}</Message>
<Form.Button disabled={!canLogin} onClick={this.login}>Login</Form.Button>
</Form>
</Segment>
</Container>
);
}
login = () => {
this.pageState.login(this.props.appState);
}
}
const DecoratedLoginPage = injectState(observer(LoginPage));
export { DecoratedLoginPage as LoginPage };