Files
deighton-ar/mobile/src/Auth/Login.js
2018-06-27 22:34:21 -07:00

222 lines
5.4 KiB
JavaScript

import React from "react"
import {
Platform,
StyleSheet,
Text,
Image,
View,
TouchableWithoutFeedback,
} from "react-native"
import { MessageModal, ApiModal, WaitModal } from "../Modal"
import logoImage from "./images/deighton.png"
import { FormBinder } from "react-form-binder"
import { api } from "../API"
import { BoundSwitch, BoundInput, BoundButton } from "../ui"
import KeyboardSpacer from "react-native-keyboard-spacer"
import { versionInfo } from "../version"
import { reactAutoBind } from "auto-bind2"
import { config } from "../config"
export class Login extends React.Component {
static bindings = {
email: {
alwaysGet: true,
isValid: (r, v) => v !== "",
},
password: {
alwaysGet: true,
isValid: (r, v) => v !== "",
},
rememberMe: {
alwaysGet: true,
isValid: true,
},
login: {
noValue: true,
isDisabled: (r) => !(r.anyModified && r.allValid),
},
}
static styles = StyleSheet.create({
page: {
minHeight: "50%",
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
inputRow: {
paddingTop: 10,
width: "60%",
flexDirection: "column",
justifyContent: "flex-end",
alignItems: "flex-start",
},
switchRow: {
paddingTop: 10,
width: "60%",
flexDirection: "row",
justifyContent: "flex-end",
alignItems: "center",
},
buttonRow: {
paddingTop: 10,
width: "60%",
flexDirection: "row",
justifyContent: "flex-end",
alignItems: "center",
},
})
constructor(props) {
super(props)
reactAutoBind(this)
this.state = {
binder: new FormBinder(
{ email: config.defaultUser, rememberMe: true },
Login.bindings
),
messageModal: null,
apiModal: null,
waitModal: null,
}
this.hiddenTouchCount = 0
}
componentWillUnmount() {
if (this.hiddenTouchTimer) {
clearTimeout(this.hiddenTouchTimer)
}
}
handleLogin() {
let obj = this.state.binder.getModifiedBindingValues()
let { history } = this.props
if (obj) {
this.setState({ waitModal: { message: "Logging In..." } })
api
.login(obj.email.trim(), obj.password, obj.rememberMe)
.then((user) => {
history.replace("/home")
})
.catch((error) => {
this.setState({
waitModal: null,
messageModal: {
icon: "hand",
message: "Unable to login",
detail: error.message,
},
})
})
}
}
handleMessageDismiss() {
this.setState({ messageModal: null })
}
handleApiDismiss(backendName) {
this.setState({ apiModal: null })
api.backend = backendName
}
handleApiPress() {
this.hiddenTouchCount += 1
if (this.hiddenTouchCount == 9) {
this.hiddenTouchCount = 0
this.setState({ apiModal: {} })
return
} else {
if (this.hiddenTouchTimer) {
clearTimeout(this.hiddenTouchTimer)
this.hiddenTouchTimer = null
}
this.hiddenTouchTimer = setTimeout(
() => (this.hiddenTouchCount = 0),
1000
)
}
}
render() {
const { messageModal, apiModal, waitModal } = this.state
return (
<View style={Login.styles.page} behavior="padding">
<TouchableWithoutFeedback onPress={this.handleApiPress}>
<Image
style={{ width: "50%" }}
source={logoImage}
resizeMode="contain"
/>
</TouchableWithoutFeedback>
<View style={Login.styles.inputRow}>
<BoundInput
name="email"
label="Email:"
placeholder="name@xyz.com"
message="Must enter a valid email"
binder={this.state.binder}
/>
</View>
<View style={Login.styles.inputRow}>
<BoundInput
name="password"
password
label="Password:"
message="Must supply a password"
binder={this.state.binder}
/>
</View>
<View style={Login.styles.switchRow}>
<BoundSwitch
name="rememberMe"
binder={this.state.binder}
label="Remember Me"
/>
</View>
<View style={Login.styles.buttonRow}>
<BoundButton
title="Login"
name="login"
width="100%"
onPress={this.handleLogin}
binder={this.state.binder}
/>
</View>
<View style={{ width: "60%", alignItems: "center" }}>
<Text
style={{
paddingTop: 15,
alignSelf: "flex-end",
color: "lightgray",
fontSize: 10,
}}>
{versionInfo.fullVersion}
</Text>
</View>
<WaitModal
open={!!waitModal}
message={waitModal ? waitModal.message : ""}
/>
<MessageModal
open={!!messageModal}
icon={messageModal ? messageModal.icon : ""}
message={messageModal ? messageModal.message : ""}
detail={messageModal ? messageModal.detail : ""}
onDismiss={messageModal && this.handleMessageDismiss}
/>
<ApiModal
open={!!apiModal}
onDismiss={apiModal && this.handleApiDismiss}
/>
{Platform.OS === "ios" && <KeyboardSpacer />}
</View>
)
}
}