First draft of connection

This commit is contained in:
Arnaud Vergnet 2020-03-29 11:47:27 +02:00
parent a533f48a12
commit fbabb4d7af
6 changed files with 228 additions and 2 deletions

View file

@ -46,6 +46,11 @@ export default class SideBar extends React.PureComponent<Props, State> {
route: "Main",
icon: "home",
},
{
name: 'LOGIN',
route: "LoginScreen",
icon: "login",
},
{
name: i18n.t('sidenav.divider2'),
route: "Divider2"

View file

@ -15,6 +15,7 @@ import Sidebar from "../components/Sidebar";
import {createStackNavigator, TransitionPresets} from "@react-navigation/stack";
import HeaderButton from "../components/HeaderButton";
import i18n from "i18n-js";
import LoginScreen from "../screens/Amicale/LoginScreen";
const defaultScreenOptions = {
gestureEnabled: true,
@ -186,6 +187,30 @@ function TetrisStackComponent() {
);
}
const LoginStack = createStackNavigator();
function LoginStackComponent() {
return (
<LoginStack.Navigator
initialRouteName="LoginScreen"
headerMode="float"
screenOptions={defaultScreenOptions}
>
<LoginStack.Screen
name="LoginScreen"
component={LoginScreen}
options={({navigation}) => {
const openDrawer = getDrawerButton.bind(this, navigation);
return {
title: 'LOGIN',
headerLeft: openDrawer
};
}}
/>
</LoginStack.Navigator>
);
}
const Drawer = createDrawerNavigator();
function getDrawerContent(props) {
@ -231,6 +256,10 @@ export default function DrawerNavigator() {
name="TetrisScreen"
component={TetrisStackComponent}
/>
<Drawer.Screen
name="LoginScreen"
component={LoginStackComponent}
/>
</Drawer.Navigator>
);
}

View file

@ -12,7 +12,9 @@
},
"jest": {
"preset": "react-native",
"setupFilesAfterEnv": ["jest-extended"]
"setupFilesAfterEnv": [
"jest-extended"
]
},
"dependencies": {
"@expo/vector-icons": "~10.0.0",
@ -42,7 +44,8 @@
"react-native-screens": "2.0.0-alpha.12",
"react-native-webview": "7.4.3",
"react-native-appearance": "~0.3.1",
"expo-linear-gradient": "~8.0.0"
"expo-linear-gradient": "~8.0.0",
"expo-secure-store": "~8.0.0"
},
"devDependencies": {
"babel-preset-expo": "^8.0.0",

View file

@ -0,0 +1,109 @@
// @flow
import * as React from 'react';
import {Keyboard, KeyboardAvoidingView, StyleSheet, TouchableWithoutFeedback, View} from "react-native";
import {Button, Text, TextInput, Title} from 'react-native-paper';
import ConnectionManager from "../../utils/ConnectionManager";
type Props = {
navigation: Object,
}
type State = {
email: string,
password: string,
}
export default class LoginScreen extends React.Component<Props, State> {
state = {
email: '',
password: '',
};
onEmailChange: Function;
onPasswordChange: Function;
constructor() {
super();
this.onEmailChange = this.onInputChange.bind(this, true);
this.onPasswordChange = this.onInputChange.bind(this, false);
}
onInputChange(isEmail: boolean, value: string) {
if (isEmail)
this.setState({email: value});
else
this.setState({password: value});
}
onSubmit() {
console.log('pressed');
ConnectionManager.getInstance().connect(this.state.email, this.state.password)
.then((data) => {
console.log(data);
})
.catch((error) => {
console.log(error);
});
}
render() {
return (
<KeyboardAvoidingView
behavior={"padding"}
contentContainerStyle={styles.container}
style={styles.container}
>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.inner}>
<Title>COUCOU</Title>
<Text>entrez vos identifiants</Text>
<TextInput
label='Email'
mode='outlined'
value={this.state.email}
onChangeText={this.onEmailChange}
/>
<TextInput
label='Password'
mode='outlined'
value={this.state.password}
onChangeText={this.onPasswordChange}
/>
<View style={styles.btnContainer}>
<Button icon="send" onPress={() => this.onSubmit()}>
LOGIN
</Button>
</View>
<Text>Pas de compte, dommage !</Text>
<View style={styles.btnContainer}>
<Button icon="send" onPress={() => console.log('Pressed')}>
Créer un compte
</Button>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
inner: {
padding: 24,
flex: 1,
},
header: {
fontSize: 36,
marginBottom: 48
},
textInput: {},
btnContainer: {
marginTop: 12
}
});

View file

@ -0,0 +1,65 @@
// @flow
export const ERROR_TYPE = {
BAD_CREDENTIALS: 0,
CONNECTION_ERROR: 1
};
const AUTH_URL = "https://www.amicale-insat.fr/api/password";
export default class ConnectionManager {
static instance: ConnectionManager | null = null;
#email: string;
#token: string;
constructor() {
}
/**
* Get this class instance or create one if none is found
* @returns {ConnectionManager}
*/
static getInstance(): ConnectionManager {
return ConnectionManager.instance === null ?
ConnectionManager.instance = new ConnectionManager() :
ConnectionManager.instance;
}
async connect(email: string, password: string) {
let data = {
email: email,
password: password,
};
return new Promise((resolve, reject) => {
fetch(AUTH_URL, {
method: 'POST',
headers: new Headers({
'Accept': 'application/json',
'Content-Type': 'application/json',
}),
body: JSON.stringify(data)
}).then(async (response) => response.json())
.then((data) => {
console.log(data);
if (this.isResponseValid(data))
resolve({success: data.success, token: data.token});
else
reject(ERROR_TYPE.BAD_CREDENTIALS);
})
.catch((error) => {
console.log(error);
reject(ERROR_TYPE.CONNECTION_ERROR);
});
});
}
isResponseValid(response: Object) {
return response !== undefined
&& response.success !== undefined
&& response.success
&& response.token !== undefined;
}
}

View file

@ -0,0 +1,15 @@
import React from 'react';
import ConnectionManager, {ERROR_TYPE} from "../ConnectionManager";
const fetch = require('isomorphic-fetch'); // fetch is not implemented in nodeJS but in react-native
const c = ConnectionManager.getInstance();
test("connect bad credentials", () => {
return expect(c.connect('truc', 'chose'))
.rejects.toBe(ERROR_TYPE.BAD_CREDENTIALS);
});
test("connect good credentials", () => {
return expect(c.connect('vergnet@etud.insa-toulouse.fr', 'Coucoù512'))
.resolves.toBe('test');
});