Merge pull request #17 from henrydays/Borges
login w/ Jwt email e password
This commit is contained in:
commit
b5e4a9bad4
126
App/app/App.js
126
App/app/App.js
|
@ -1,6 +1,7 @@
|
|||
/**
|
||||
* Sample React Native App
|
||||
* https://github.com/facebook/react-native
|
||||
* Enei 2019 React Native App
|
||||
*
|
||||
* João Borges
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
|
@ -9,26 +10,58 @@
|
|||
import React, {Component} from 'react';
|
||||
import Icon from 'react-native-vector-icons/AntDesign';
|
||||
import AppIntroSlider from 'react-native-app-intro-slider'
|
||||
|
||||
import {Platform, StyleSheet, Text, View, StatusBar} from 'react-native';
|
||||
import Routes from './Router'
|
||||
|
||||
import deviceStorage from '././services/deviceStorage'
|
||||
|
||||
import Router from './Router'
|
||||
import Login from './screens/Login'
|
||||
import {AsyncStorage, ActivityIndicator} from 'react-native';
|
||||
import AuthLoadingScreen from "./screens/AuthLoading";
|
||||
|
||||
export default class App extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showRealApp: false,
|
||||
firstLogin: null,
|
||||
jwt: '',
|
||||
loading: true
|
||||
};
|
||||
}
|
||||
|
||||
renderApp = () => (
|
||||
<View style={{flex: 1}}>
|
||||
<Routes />
|
||||
</View>
|
||||
);
|
||||
newJWT(jwt) {
|
||||
this.setState({
|
||||
jwt: jwt
|
||||
});
|
||||
}
|
||||
|
||||
//componentDidMount() is invoked immediately after a component is mounted
|
||||
/*componentDidMount() {
|
||||
|
||||
|
||||
AsyncStorage.removeItem('firstLogin');
|
||||
|
||||
AsyncStorage.getItem('firstLogin').then((value) => {
|
||||
|
||||
console.log('aqui')
|
||||
if (value == null) {
|
||||
//setItem (key: string, value: string)
|
||||
deviceStorage.saveItem('firstLogin', JSON.stringify(true));
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
//this.setState({firstLogin: false});
|
||||
}
|
||||
|
||||
this.setState({loading: false});
|
||||
|
||||
})
|
||||
}*/
|
||||
|
||||
|
||||
//Buttons do Intro Slider
|
||||
_renderNextButton = () => {
|
||||
return (
|
||||
<View style={styles.buttonCircle}>
|
||||
|
@ -36,7 +69,7 @@ export default class App extends Component {
|
|||
name='right'
|
||||
color='rgba(255, 255, 255, .9)'
|
||||
size={24}
|
||||
style={{ backgroundColor: 'transparent' }} />
|
||||
style={{backgroundColor: 'transparent'}}/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
@ -48,38 +81,56 @@ export default class App extends Component {
|
|||
name='check'
|
||||
color='rgba(255, 255, 255, .9)'
|
||||
size={24}
|
||||
style={{ backgroundColor: 'transparent' }}
|
||||
style={{backgroundColor: 'transparent'}}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
_onDone = () => {
|
||||
|
||||
this.state({ showRealApp: true });
|
||||
};
|
||||
|
||||
|
||||
//--Buttons do Intro Slider
|
||||
|
||||
render() {
|
||||
if (this.state.showRealApp) {
|
||||
return (
|
||||
this.renderApp()
|
||||
);
|
||||
}
|
||||
else {
|
||||
return(
|
||||
<AppIntroSlider
|
||||
slides={slides}
|
||||
renderDoneButton={this._renderDoneButton}
|
||||
renderNextButton={this._renderNextButton}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
console.log('inside render');
|
||||
|
||||
return (
|
||||
<Router />
|
||||
)
|
||||
|
||||
|
||||
/* if (this.state.loading) {
|
||||
}
|
||||
else {
|
||||
|
||||
if (this.state.firstLaunch) {
|
||||
return (
|
||||
<AppIntroSlider
|
||||
slides={slides}
|
||||
renderDoneButton={this._renderDoneButton}
|
||||
renderNextButton={this._renderNextButton}
|
||||
onDone={() => this.setState({firstLaunch: false})}
|
||||
/>
|
||||
);
|
||||
}
|
||||
else if (!this.state.firstLaunch && !this.state.jwt) { //&& !this.state.jwt}
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
||||
<Login/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
else { // !this.state.firstLaunch && this.state.jwt
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
||||
<Routes />
|
||||
</View>
|
||||
)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Styles
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -88,16 +139,6 @@ const styles = StyleSheet.create({
|
|||
alignItems: 'center',
|
||||
backgroundColor: '#F5FCFF',
|
||||
},
|
||||
welcome: {
|
||||
fontSize: 20,
|
||||
textAlign: 'center',
|
||||
margin: 10,
|
||||
},
|
||||
instructions: {
|
||||
textAlign: 'center',
|
||||
color: '#333333',
|
||||
marginBottom: 5,
|
||||
},
|
||||
|
||||
buttonCircle: {
|
||||
width: 40,
|
||||
|
@ -114,7 +155,6 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
|
||||
|
||||
//Introducing Slides
|
||||
const slides = [
|
||||
{
|
||||
|
|
|
@ -14,6 +14,11 @@ export const validation = {
|
|||
presence: {
|
||||
message: 'Introduza uma password'
|
||||
},
|
||||
},
|
||||
new_password: {
|
||||
presence: {
|
||||
message: 'Introduza uma password'
|
||||
},
|
||||
length: {
|
||||
minimum: {
|
||||
value: 6,
|
||||
|
|
|
@ -1,11 +1,46 @@
|
|||
import React from 'react';
|
||||
import { createStackNavigator, createAppContainer } from 'react-navigation';
|
||||
import {
|
||||
createStackNavigator,
|
||||
createAppContainer,
|
||||
createSwitchNavigator,
|
||||
createBottomTabNavigator
|
||||
} from 'react-navigation';
|
||||
import * as Screens from './screens';
|
||||
import Login from './screens/Login'
|
||||
import AuthLoadingScreen from './screens/AuthLoading'
|
||||
|
||||
const ExplorerApp = createStackNavigator({
|
||||
Home: { screen: Screens.Home },
|
||||
Login: { screen: Screens.Login}
|
||||
const AppStack = createBottomTabNavigator(
|
||||
{
|
||||
Home: {
|
||||
screen: Screens.Home
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
const AuthStack = createStackNavigator(
|
||||
{
|
||||
Login: {
|
||||
screen: Login,
|
||||
},
|
||||
},
|
||||
/*{
|
||||
headerMode: 'none',
|
||||
navigationOptions: {
|
||||
headerVisible: false,
|
||||
}
|
||||
}*/
|
||||
|
||||
);
|
||||
|
||||
|
||||
export default createAppContainer(createSwitchNavigator(
|
||||
{
|
||||
AuthLoading: AuthLoadingScreen,
|
||||
App: AppStack,
|
||||
Auth: AuthStack,
|
||||
},
|
||||
{
|
||||
initialRouteName: 'AuthLoading'
|
||||
})
|
||||
);
|
||||
|
||||
export default createAppContainer(ExplorerApp);
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 8.0 KiB |
|
@ -5,6 +5,13 @@ export const UtilStyles = StyleSheet.create({
|
|||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: 'white',
|
||||
|
||||
},
|
||||
containerLoading: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F5FCFF',
|
||||
},
|
||||
titleText: {
|
||||
fontSize: 20,
|
||||
|
@ -90,6 +97,14 @@ export const UtilStyles = StyleSheet.create({
|
|||
},
|
||||
|
||||
|
||||
loginImage: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
alignSelf: 'center',
|
||||
width: 160,
|
||||
height: 149.2,
|
||||
},
|
||||
|
||||
//------------------//
|
||||
inputLabel: {
|
||||
paddingBottom: 15
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import React, {Component} from 'react';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
AsyncStorage,
|
||||
Button,
|
||||
StatusBar,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import {UtilStyles} from '../assets/styles'
|
||||
|
||||
export default class AuthLoadingScreen extends Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._bootstrapAsync();
|
||||
}
|
||||
|
||||
// Fetch the token from storage then navigate to our appropriate place
|
||||
_bootstrapAsync = async () => {
|
||||
const token = await AsyncStorage.getItem('userToken');
|
||||
|
||||
// This will switch to the App screen or Auth screen and this loading
|
||||
// screen will be unmounted and thrown away.
|
||||
this.props.navigation.navigate(token ? 'App' : 'Auth');
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Render Loading
|
||||
render() {
|
||||
return (
|
||||
<View style={UtilStyles.containerLoading}>
|
||||
<ActivityIndicator size='large' color="rgba(000,000,000,1)"/>
|
||||
<StatusBar barStyle="default" />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -3,22 +3,25 @@ import { Button, View, Text } from 'react-native';
|
|||
import {RkButton,
|
||||
RkTheme } from 'react-native-ui-kitten';
|
||||
|
||||
import deviceStorage from '../services/deviceStorage';
|
||||
|
||||
export class Home extends Component {
|
||||
|
||||
static navigationOptions = {
|
||||
title: 'Home'
|
||||
};
|
||||
|
||||
|
||||
_deleteToken = () => {
|
||||
deviceStorage.deleteJWT();
|
||||
};
|
||||
|
||||
|
||||
render() {
|
||||
const {navigate} = this.props.navigation;
|
||||
const { navigate } = this.props.navigation;
|
||||
return (
|
||||
<View style={{
|
||||
flex: 1,
|
||||
alignItems:'center',
|
||||
justifyContent:'center'
|
||||
}}>
|
||||
<RkButton title="Go to Login screen"
|
||||
onPress={() => this.props.navigation.navigate('Login')}/>
|
||||
<View style={{flex:1, alignItems: 'center', alignContent: 'center'}}>
|
||||
<RkButton onPress= { () => this._deleteToken() }>Apagar Token</RkButton>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, {Component, Fragment} from 'react'
|
||||
import {View, Text, TextInput} from 'react-native'
|
||||
import {View, Text, TextInput, Image, ScrollView} from 'react-native'
|
||||
import {RkTheme, RkButton, RkTextInput, RkText} from 'react-native-ui-kitten'
|
||||
|
||||
import {UtilStyles} from '../assets/styles'
|
||||
|
@ -8,10 +8,11 @@ import {Validate} from '../Helpers/Validation'
|
|||
import axios from 'axios';
|
||||
import deviceStorage from '../services/deviceStorage';
|
||||
|
||||
export class Login extends Component {
|
||||
|
||||
static navigationOptions = {
|
||||
title: ''
|
||||
export default class Login extends Component {
|
||||
|
||||
static navigationOptions = {
|
||||
header: null,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
|
@ -19,6 +20,8 @@ export class Login extends Component {
|
|||
|
||||
this.state = {
|
||||
|
||||
formValid: false,
|
||||
|
||||
email: '',
|
||||
emailError: false,
|
||||
emailErrorMessage: '',
|
||||
|
@ -29,65 +32,101 @@ export class Login extends Component {
|
|||
|
||||
loading: false
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
_validatelogin = (email, password) => {
|
||||
let valid = null;
|
||||
|
||||
let v = Validate('email', email);
|
||||
this.setState({emailError: v[0], emailErrorMessage: v[1]});
|
||||
|
||||
v = Validate('password', password);
|
||||
|
||||
// setState is asynchronous and so trying to work with state directly after a setState
|
||||
// call won't work as the update won't necessarily have run. Instead you can use the second argument to setState which is a callback
|
||||
this.setState({passwordError: v[0], passwordErrorMessage: v[1]}, function () {
|
||||
|
||||
console.log('Email error: ' + this.state.emailError + ' Pass Error: ' + this.state.passwordError);
|
||||
|
||||
});
|
||||
|
||||
if (this.state.emailError && this.state.passwordError)
|
||||
this.setState({formValid: false});
|
||||
else
|
||||
this.setState({formValid: true});
|
||||
};
|
||||
|
||||
|
||||
login() {
|
||||
const {email, password, formValid} = this.state;
|
||||
this.setState({loading: true});
|
||||
|
||||
this.setState({ error: '', loading: true });
|
||||
this._validatelogin(email, password);
|
||||
|
||||
// NOTE HTTP is insecure, only post to HTTPS in production apps
|
||||
console.log(formValid);
|
||||
|
||||
axios.post("http://localhost:4000/api/v1/sign_up",{
|
||||
user: {
|
||||
email: this.state.email,
|
||||
password: this.state.password,
|
||||
}
|
||||
},)
|
||||
.then((response) => {
|
||||
// Handle the JWT response here
|
||||
deviceStorage.saveItem('id_token', response.data.jwt);
|
||||
})
|
||||
.catch((error) => {
|
||||
// Handle returned errors here
|
||||
});
|
||||
if (formValid) {
|
||||
|
||||
axios.post("https://reqres.in/api/login", {
|
||||
|
||||
email: email,
|
||||
password: password
|
||||
|
||||
}) //https://reqres.in/api/login email: email, password: password,
|
||||
.then(response => {
|
||||
console.log(response)
|
||||
// Save Token
|
||||
deviceStorage.saveItem('userToken', response.data.token);
|
||||
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {navigate} = this.props.navigation;
|
||||
//const { email, password, error, loading } = this.state;
|
||||
|
||||
return (
|
||||
<ScrollView>
|
||||
<View style={[UtilStyles.section, {backgroundColor: RkTheme.current.colors.input}]}>
|
||||
<Image style={UtilStyles.loginImage}
|
||||
source={require('../assets/img/logo.png')}
|
||||
/>
|
||||
|
||||
<View style={[UtilStyles.section, {backgroundColor: RkTheme.current.colors.input}]}>
|
||||
<View style={UtilStyles.rowContainer}>
|
||||
<View style={{flex: 1}}>
|
||||
<RkTextInput rkType='rounded' style={ this.state.emailError ? UtilStyles.errorInput : ''}
|
||||
placeholder='Login' keyboardType='email-address'
|
||||
onChangeText={ (email) => {
|
||||
this.setState({email: email});
|
||||
let v = Validate('email', email);
|
||||
this.setState({emailError: v[0], emailErrorMessage: v[1]})
|
||||
}}
|
||||
value={this.state.email}
|
||||
/>
|
||||
{this.state.emailError && <RkText style={UtilStyles.errorMsg}>{this.state.emailErrorMessage}</RkText>}
|
||||
<RkTextInput
|
||||
secureTextEntry={true} style={ this.state.passwordError ? UtilStyles.errorInput : '' }
|
||||
rkType='rounded' placeholder='Password'
|
||||
onChangeText={ (password) => {
|
||||
this.setState({password: password});
|
||||
let v = Validate('password', password);
|
||||
this.setState({passwordError: v[0], passwordErrorMessage: v[1]})
|
||||
}}
|
||||
/>
|
||||
{this.state.passwordError && <RkText style={UtilStyles.errorMsg}>{this.state.passwordErrorMessage}</RkText>}
|
||||
<View style={UtilStyles.rowContainer}>
|
||||
<View style={{flex: 1}}>
|
||||
<RkTextInput rkType='rounded' style={this.state.emailError ? UtilStyles.errorInput : ''}
|
||||
placeholder='Login' keyboardType='email-address'
|
||||
onChangeText={(email) => {
|
||||
this.setState({email: email});
|
||||
}}
|
||||
value={this.state.email}
|
||||
/>
|
||||
{this.state.emailError &&
|
||||
<RkText style={UtilStyles.errorMsg}>{this.state.emailErrorMessage}</RkText>}
|
||||
<RkTextInput
|
||||
secureTextEntry={true} style={this.state.passwordError ? UtilStyles.errorInput : ''}
|
||||
rkType='rounded' placeholder='Password'
|
||||
onChangeText={(pass) => {
|
||||
this.setState({password: pass});
|
||||
}}
|
||||
value={this.state.password}
|
||||
|
||||
/>
|
||||
{this.state.passwordError &&
|
||||
<RkText style={UtilStyles.errorMsg}>{this.state.passwordErrorMessage}</RkText>}
|
||||
</View>
|
||||
</View>
|
||||
<RkButton style={{marginTop: 30}} rkType='rounded xlarge' onPress={() => this.login()}>
|
||||
Login
|
||||
</RkButton>
|
||||
</View>
|
||||
<RkButton rkType='rounded xlarge' onPress={() => this.login()}>
|
||||
Login
|
||||
</RkButton>
|
||||
</View>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
export * from './Home';
|
||||
export * from './Login';
|
||||
export * from './Home';
|
|
@ -5,16 +5,16 @@ const deviceStorage = {
|
|||
async saveItem(key, value) {
|
||||
try {
|
||||
await AsyncStorage.setItem(key, value);
|
||||
console.log('saved')
|
||||
} catch (error) {
|
||||
console.log(`Erro a guardar! \n${error.message}`);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
//Carregar token
|
||||
async loadJWT() {
|
||||
try {
|
||||
const value = await AsyncStorage.getItem('id_token');
|
||||
const value = await AsyncStorage.getItem('userToken');
|
||||
if (value !== null) {
|
||||
this.setState({
|
||||
jwt: value,
|
||||
|
@ -33,22 +33,15 @@ const deviceStorage = {
|
|||
|
||||
//Apagar Token
|
||||
async deleteJWT() {
|
||||
try{
|
||||
await AsyncStorage.removeItem('id_token')
|
||||
.then(
|
||||
() => {
|
||||
this.setState({
|
||||
jwt: ''
|
||||
})
|
||||
}
|
||||
);
|
||||
try {
|
||||
await AsyncStorage.removeItem('userToken');
|
||||
|
||||
} catch (error) {
|
||||
console.log(`Erro a ler token \n${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
export default deviceStorage;
|
Loading…
Reference in New Issue