forked from vergnet/application-amicale
Implemented base vote screen and updated ConnectionManager.js to match new protocol
This commit is contained in:
parent
7b332e11fc
commit
e1a57487a2
9 changed files with 358 additions and 182 deletions
|
@ -65,84 +65,64 @@ test('recoverLogin success saved', () => {
|
|||
|
||||
test('isRequestResponseValid', () => {
|
||||
let json = {
|
||||
state: true,
|
||||
error: 0,
|
||||
data: {}
|
||||
};
|
||||
expect(c.isRequestResponseValid(json)).toBeTrue();
|
||||
expect(c.isResponseValid(json)).toBeTrue();
|
||||
json = {
|
||||
state: false,
|
||||
error: 1,
|
||||
data: {}
|
||||
};
|
||||
expect(c.isRequestResponseValid(json)).toBeTrue();
|
||||
expect(c.isResponseValid(json)).toBeTrue();
|
||||
json = {
|
||||
state: false,
|
||||
message: 'coucou',
|
||||
error: 50,
|
||||
data: {}
|
||||
};
|
||||
expect(c.isResponseValid(json)).toBeTrue();
|
||||
json = {
|
||||
error: 50,
|
||||
data: {truc: 'machin'}
|
||||
};
|
||||
expect(c.isRequestResponseValid(json)).toBeTrue();
|
||||
expect(c.isResponseValid(json)).toBeTrue();
|
||||
json = {
|
||||
message: 'coucou'
|
||||
};
|
||||
expect(c.isRequestResponseValid(json)).toBeFalse();
|
||||
expect(c.isResponseValid(json)).toBeFalse();
|
||||
json = {
|
||||
state: 'coucou'
|
||||
error: 'coucou',
|
||||
data: {truc: 'machin'}
|
||||
};
|
||||
expect(c.isRequestResponseValid(json)).toBeFalse();
|
||||
expect(c.isResponseValid(json)).toBeFalse();
|
||||
json = {
|
||||
state: true,
|
||||
error: 0,
|
||||
data: 'coucou'
|
||||
};
|
||||
expect(c.isRequestResponseValid(json)).toBeFalse();
|
||||
expect(c.isResponseValid(json)).toBeFalse();
|
||||
json = {
|
||||
error: 0,
|
||||
};
|
||||
expect(c.isResponseValid(json)).toBeFalse();
|
||||
});
|
||||
|
||||
test("isConnectionResponseValid", () => {
|
||||
let json = {
|
||||
state: true,
|
||||
message: 'Connexion confirmée',
|
||||
token: 'token'
|
||||
error: 0,
|
||||
data: {token: 'token'}
|
||||
};
|
||||
expect(c.isConnectionResponseValid(json)).toBeTrue();
|
||||
json = {
|
||||
state: true,
|
||||
token: 'token'
|
||||
error: 2,
|
||||
data: {}
|
||||
};
|
||||
expect(c.isConnectionResponseValid(json)).toBeTrue();
|
||||
json = {
|
||||
state: false,
|
||||
};
|
||||
expect(c.isConnectionResponseValid(json)).toBeTrue();
|
||||
json = {
|
||||
state: false,
|
||||
message: 'Adresse mail ou mot de passe incorrect',
|
||||
token: ''
|
||||
};
|
||||
expect(c.isConnectionResponseValid(json)).toBeTrue();
|
||||
json = {
|
||||
state: true,
|
||||
message: 'Connexion confirmée',
|
||||
token: ''
|
||||
error: 0,
|
||||
data: {token: ''}
|
||||
};
|
||||
expect(c.isConnectionResponseValid(json)).toBeFalse();
|
||||
json = {
|
||||
state: true,
|
||||
message: 'Connexion confirmée',
|
||||
};
|
||||
expect(c.isConnectionResponseValid(json)).toBeFalse();
|
||||
json = {
|
||||
state: 'coucou',
|
||||
message: 'Connexion confirmée',
|
||||
token: 'token'
|
||||
};
|
||||
expect(c.isConnectionResponseValid(json)).toBeFalse();
|
||||
json = {
|
||||
state: true,
|
||||
message: 'Connexion confirmée',
|
||||
token: 2
|
||||
};
|
||||
expect(c.isConnectionResponseValid(json)).toBeFalse();
|
||||
json = {
|
||||
coucou: 'coucou',
|
||||
message: 'Connexion confirmée',
|
||||
token: 'token'
|
||||
error: 'prout',
|
||||
data: {token: ''}
|
||||
};
|
||||
expect(c.isConnectionResponseValid(json)).toBeFalse();
|
||||
});
|
||||
|
@ -152,10 +132,9 @@ test("connect bad credentials", () => {
|
|||
return Promise.resolve({
|
||||
json: () => {
|
||||
return {
|
||||
state: false,
|
||||
message: 'Adresse mail ou mot de passe incorrect',
|
||||
token: ''
|
||||
}
|
||||
error: ERROR_TYPE.BAD_CREDENTIALS,
|
||||
data: {}
|
||||
};
|
||||
},
|
||||
})
|
||||
});
|
||||
|
@ -168,10 +147,9 @@ test("connect good credentials", () => {
|
|||
return Promise.resolve({
|
||||
json: () => {
|
||||
return {
|
||||
state: true,
|
||||
message: 'Connexion confirmée',
|
||||
token: 'token'
|
||||
}
|
||||
error: ERROR_TYPE.SUCCESS,
|
||||
data: {token: 'token'}
|
||||
};
|
||||
},
|
||||
})
|
||||
});
|
||||
|
@ -186,13 +164,9 @@ test("connect good credentials no consent", () => {
|
|||
return Promise.resolve({
|
||||
json: () => {
|
||||
return {
|
||||
state: false,
|
||||
message: 'pas de consent',
|
||||
token: '',
|
||||
data: {
|
||||
consent: false,
|
||||
}
|
||||
}
|
||||
error: ERROR_TYPE.NO_CONSENT,
|
||||
data: {}
|
||||
};
|
||||
},
|
||||
})
|
||||
});
|
||||
|
@ -205,17 +179,16 @@ test("connect good credentials, fail save token", () => {
|
|||
return Promise.resolve({
|
||||
json: () => {
|
||||
return {
|
||||
state: true,
|
||||
message: 'Connexion confirmée',
|
||||
token: 'token'
|
||||
}
|
||||
error: ERROR_TYPE.SUCCESS,
|
||||
data: {token: 'token'}
|
||||
};
|
||||
},
|
||||
})
|
||||
});
|
||||
jest.spyOn(ConnectionManager.prototype, 'saveLogin').mockImplementationOnce(() => {
|
||||
return Promise.reject(false);
|
||||
});
|
||||
return expect(c.connect('email', 'password')).rejects.toBe(ERROR_TYPE.SAVE_TOKEN);
|
||||
return expect(c.connect('email', 'password')).rejects.toBe(ERROR_TYPE.UNKNOWN);
|
||||
});
|
||||
|
||||
test("connect connection error", () => {
|
||||
|
@ -249,7 +222,10 @@ test("authenticatedRequest success", () => {
|
|||
jest.spyOn(global, 'fetch').mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
json: () => {
|
||||
return {state: true, message: 'Connexion vérifiée', data: {coucou: 'toi'}}
|
||||
return {
|
||||
error: ERROR_TYPE.SUCCESS,
|
||||
data: {coucou: 'toi'}
|
||||
};
|
||||
},
|
||||
})
|
||||
});
|
||||
|
@ -264,12 +240,15 @@ test("authenticatedRequest error wrong token", () => {
|
|||
jest.spyOn(global, 'fetch').mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
json: () => {
|
||||
return {state: false, message: 'Le champ token sélectionné est invalide.'}
|
||||
return {
|
||||
error: ERROR_TYPE.BAD_TOKEN,
|
||||
data: {}
|
||||
};
|
||||
},
|
||||
})
|
||||
});
|
||||
return expect(c.authenticatedRequest('https://www.amicale-insat.fr/api/token/check'))
|
||||
.rejects.toBe(ERROR_TYPE.BAD_CREDENTIALS);
|
||||
.rejects.toBe(ERROR_TYPE.BAD_TOKEN);
|
||||
});
|
||||
|
||||
test("authenticatedRequest error bogus response", () => {
|
||||
|
@ -279,7 +258,9 @@ test("authenticatedRequest error bogus response", () => {
|
|||
jest.spyOn(global, 'fetch').mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
json: () => {
|
||||
return {state: true, message: 'Connexion vérifiée'}
|
||||
return {
|
||||
error: ERROR_TYPE.SUCCESS,
|
||||
};
|
||||
},
|
||||
})
|
||||
});
|
||||
|
@ -302,13 +283,6 @@ test("authenticatedRequest error no token", () => {
|
|||
jest.spyOn(ConnectionManager.prototype, 'getToken').mockImplementationOnce(() => {
|
||||
return null;
|
||||
});
|
||||
jest.spyOn(global, 'fetch').mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
json: () => {
|
||||
return {state: false, message: 'Le champ token sélectionné est invalide.'}
|
||||
},
|
||||
})
|
||||
});
|
||||
return expect(c.authenticatedRequest('https://www.amicale-insat.fr/api/token/check'))
|
||||
.rejects.toBe(ERROR_TYPE.NO_TOKEN);
|
||||
.rejects.toBe(ERROR_TYPE.UNKNOWN);
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ import BasicLoadingScreen from "../Custom/BasicLoadingScreen";
|
|||
type Props = {
|
||||
navigation: Object,
|
||||
theme: Object,
|
||||
link: string,
|
||||
links: Array<{link: string, mandatory: boolean}>,
|
||||
renderFunction: Function,
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ class AuthenticatedScreen extends React.Component<Props, State> {
|
|||
currentUserToken: string | null;
|
||||
connectionManager: ConnectionManager;
|
||||
errorCode: number;
|
||||
data: Object;
|
||||
data: Array<Object>;
|
||||
colors: Object;
|
||||
|
||||
constructor(props) {
|
||||
|
@ -35,6 +35,7 @@ class AuthenticatedScreen extends React.Component<Props, State> {
|
|||
this.colors = props.theme.colors;
|
||||
this.connectionManager = ConnectionManager.getInstance();
|
||||
this.props.navigation.addListener('focus', this.onScreenFocus.bind(this));
|
||||
this.data = new Array(this.props.links.length);
|
||||
}
|
||||
|
||||
onScreenFocus() {
|
||||
|
@ -46,25 +47,53 @@ class AuthenticatedScreen extends React.Component<Props, State> {
|
|||
if (!this.state.loading)
|
||||
this.setState({loading: true});
|
||||
if (this.connectionManager.isLoggedIn()) {
|
||||
this.connectionManager.authenticatedRequest(this.props.link)
|
||||
.then((data) => {
|
||||
this.onFinishedLoading(data, -1);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.onFinishedLoading(undefined, error);
|
||||
});
|
||||
for (let i = 0; i < this.props.links.length; i++) {
|
||||
this.connectionManager.authenticatedRequest(this.props.links[i].link)
|
||||
.then((data) => {
|
||||
this.onFinishedLoading(data, i, -1);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.onFinishedLoading(null, i, error);
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
this.onFinishedLoading(undefined, ERROR_TYPE.BAD_CREDENTIALS);
|
||||
this.onFinishedLoading(null, -1, ERROR_TYPE.BAD_CREDENTIALS);
|
||||
}
|
||||
};
|
||||
|
||||
onFinishedLoading(data: Object, error: number) {
|
||||
this.data = data;
|
||||
onFinishedLoading(data: Object, index: number, error: number) {
|
||||
if (index >= 0 && index < this.props.links.length)
|
||||
this.data[index] = data;
|
||||
this.currentUserToken = data !== undefined
|
||||
? this.connectionManager.getToken()
|
||||
: null;
|
||||
this.errorCode = error;
|
||||
this.setState({loading: false});
|
||||
|
||||
if (this.allRequestsFinished())
|
||||
this.setState({loading: false});
|
||||
}
|
||||
|
||||
allRequestsFinished() {
|
||||
let finished = true;
|
||||
for (let i = 0; i < this.data.length; i++) {
|
||||
if (this.data[i] === undefined) {
|
||||
finished = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
allRequestsValid() {
|
||||
let valid = true;
|
||||
for (let i = 0; i < this.data.length; i++) {
|
||||
if (this.data[i] === null && this.props.links[i].mandatory) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
getErrorRender() {
|
||||
|
@ -75,6 +104,10 @@ class AuthenticatedScreen extends React.Component<Props, State> {
|
|||
message = i18n.t("loginScreen.errors.credentials");
|
||||
icon = "account-alert-outline";
|
||||
break;
|
||||
case ERROR_TYPE.BAD_TOKEN:
|
||||
message = "BAD TOKEN"; // TODO translate
|
||||
icon = "access-point-network-off";
|
||||
break;
|
||||
case ERROR_TYPE.CONNECTION_ERROR:
|
||||
message = i18n.t("loginScreen.errors.connection");
|
||||
icon = "access-point-network-off";
|
||||
|
@ -99,7 +132,7 @@ class AuthenticatedScreen extends React.Component<Props, State> {
|
|||
return (
|
||||
this.state.loading
|
||||
? <BasicLoadingScreen/>
|
||||
: (this.data !== undefined
|
||||
: (this.allRequestsValid()
|
||||
? this.props.renderFunction(this.data)
|
||||
: this.getErrorRender())
|
||||
);
|
||||
|
|
|
@ -69,6 +69,12 @@ class SideBar extends React.Component<Props, State> {
|
|||
icon: "account-group",
|
||||
onlyWhenLoggedIn: true,
|
||||
},
|
||||
{
|
||||
name: "VOTE",
|
||||
route: "VoteScreen",
|
||||
icon: "vote",
|
||||
onlyWhenLoggedIn: true,
|
||||
},
|
||||
{
|
||||
name: i18n.t('screens.logout'),
|
||||
route: 'disconnect',
|
||||
|
|
|
@ -3,14 +3,35 @@
|
|||
import * as SecureStore from 'expo-secure-store';
|
||||
|
||||
export const ERROR_TYPE = {
|
||||
BAD_CREDENTIALS: 0,
|
||||
CONNECTION_ERROR: 1,
|
||||
SAVE_TOKEN: 2,
|
||||
NO_TOKEN: 3,
|
||||
NO_CONSENT: 4,
|
||||
SUCCESS: 0,
|
||||
BAD_CREDENTIALS: 1,
|
||||
BAD_TOKEN: 2,
|
||||
NO_CONSENT: 3,
|
||||
BAD_INPUT: 400,
|
||||
FORBIDDEN: 403,
|
||||
CONNECTION_ERROR: 404,
|
||||
SERVER_ERROR: 500,
|
||||
UNKNOWN: 999,
|
||||
};
|
||||
|
||||
const AUTH_URL = "https://www.amicale-insat.fr/api/password";
|
||||
type response_format = {
|
||||
error: number,
|
||||
data: Object,
|
||||
}
|
||||
|
||||
/**
|
||||
* champ: error
|
||||
*
|
||||
* 0 : SUCCESS -> pas d'erreurs
|
||||
* 1 : BAD_CREDENTIALS -> email ou mdp invalide
|
||||
* 2 : BAD_TOKEN -> session expirée
|
||||
* 3 : NO_CONSENT
|
||||
* 403 : FORBIDDEN -> accès a la ressource interdit
|
||||
* 500 : SERVER_ERROR -> pb coté serveur
|
||||
*/
|
||||
|
||||
const API_ENDPOINT = "https://www.amicale-insat.fr/api/";
|
||||
const AUTH_PATH = "password";
|
||||
|
||||
export default class ConnectionManager {
|
||||
static instance: ConnectionManager | null = null;
|
||||
|
@ -110,7 +131,7 @@ export default class ConnectionManager {
|
|||
password: password,
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(AUTH_URL, {
|
||||
fetch(API_ENDPOINT + AUTH_PATH, {
|
||||
method: 'POST',
|
||||
headers: new Headers({
|
||||
'Accept': 'application/json',
|
||||
|
@ -118,22 +139,18 @@ export default class ConnectionManager {
|
|||
}),
|
||||
body: JSON.stringify(data)
|
||||
}).then(async (response) => response.json())
|
||||
.then((data) => {
|
||||
if (this.isConnectionResponseValid(data)) {
|
||||
if (data.state) {
|
||||
this.saveLogin(email, data.token)
|
||||
.then((response: response_format) => {
|
||||
if (this.isConnectionResponseValid(response)) {
|
||||
if (response.error === ERROR_TYPE.SUCCESS) {
|
||||
this.saveLogin(email, response.data.token)
|
||||
.then(() => {
|
||||
resolve(true);
|
||||
})
|
||||
.catch(() => {
|
||||
reject(ERROR_TYPE.SAVE_TOKEN);
|
||||
reject(ERROR_TYPE.UNKNOWN);
|
||||
});
|
||||
} else if (data.data !== undefined
|
||||
&& data.data.consent !== undefined
|
||||
&& !data.data.consent)
|
||||
reject(ERROR_TYPE.NO_CONSENT);
|
||||
else
|
||||
reject(ERROR_TYPE.BAD_CREDENTIALS);
|
||||
} else
|
||||
reject(response.error);
|
||||
} else
|
||||
reject(ERROR_TYPE.CONNECTION_ERROR);
|
||||
})
|
||||
|
@ -143,35 +160,32 @@ export default class ConnectionManager {
|
|||
});
|
||||
}
|
||||
|
||||
isRequestResponseValid(response: Object) {
|
||||
isResponseValid(response: response_format) {
|
||||
let valid = response !== undefined
|
||||
&& response.state !== undefined
|
||||
&& typeof response.state === "boolean";
|
||||
&& response.error !== undefined
|
||||
&& typeof response.error === "number";
|
||||
|
||||
if (valid && response.state)
|
||||
valid = valid
|
||||
&& response.data !== undefined
|
||||
&& typeof response.data === "object";
|
||||
valid = valid
|
||||
&& response.data !== undefined
|
||||
&& typeof response.data === "object";
|
||||
return valid;
|
||||
}
|
||||
|
||||
isConnectionResponseValid(response: Object) {
|
||||
let valid = response !== undefined
|
||||
&& response.state !== undefined
|
||||
&& typeof response.state === "boolean";
|
||||
isConnectionResponseValid(response: response_format) {
|
||||
let valid = this.isResponseValid(response);
|
||||
|
||||
if (valid && response.state)
|
||||
if (valid && response.error === ERROR_TYPE.SUCCESS)
|
||||
valid = valid
|
||||
&& response.token !== undefined
|
||||
&& response.token !== ''
|
||||
&& typeof response.token === "string";
|
||||
&& response.data.token !== undefined
|
||||
&& response.data.token !== ''
|
||||
&& typeof response.data.token === "string";
|
||||
return valid;
|
||||
}
|
||||
|
||||
async authenticatedRequest(url: string) {
|
||||
async authenticatedRequest(path: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.getToken() !== null) {
|
||||
fetch(url, {
|
||||
fetch(API_ENDPOINT + path, {
|
||||
method: 'POST',
|
||||
headers: new Headers({
|
||||
'Accept': 'application/json',
|
||||
|
@ -179,12 +193,13 @@ export default class ConnectionManager {
|
|||
}),
|
||||
body: JSON.stringify({token: this.getToken()})
|
||||
}).then(async (response) => response.json())
|
||||
.then((data) => {
|
||||
if (this.isRequestResponseValid(data)) {
|
||||
if (data.state)
|
||||
resolve(data.data);
|
||||
.then((response: response_format) => {
|
||||
console.log(response);
|
||||
if (this.isResponseValid(response)) {
|
||||
if (response.error === ERROR_TYPE.SUCCESS)
|
||||
resolve(response.data);
|
||||
else
|
||||
reject(ERROR_TYPE.BAD_CREDENTIALS);
|
||||
reject(response.error);
|
||||
} else
|
||||
reject(ERROR_TYPE.CONNECTION_ERROR);
|
||||
})
|
||||
|
@ -192,7 +207,7 @@ export default class ConnectionManager {
|
|||
reject(ERROR_TYPE.CONNECTION_ERROR);
|
||||
});
|
||||
} else
|
||||
reject(ERROR_TYPE.NO_TOKEN);
|
||||
reject(ERROR_TYPE.UNKNOWN);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import ProfileScreen from "../screens/Amicale/ProfileScreen";
|
|||
import ClubListScreen from "../screens/Amicale/Clubs/ClubListScreen";
|
||||
import ClubDisplayScreen from "../screens/Amicale/Clubs/ClubDisplayScreen";
|
||||
import ClubAboutScreen from "../screens/Amicale/Clubs/ClubAboutScreen";
|
||||
import VoteScreen from "../screens/Amicale/VoteScreen";
|
||||
|
||||
const defaultScreenOptions = {
|
||||
gestureEnabled: true,
|
||||
|
@ -239,6 +240,31 @@ function ProfileStackComponent() {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
const VoteStack = createStackNavigator();
|
||||
|
||||
function VoteStackComponent() {
|
||||
return (
|
||||
<VoteStack.Navigator
|
||||
initialRouteName="VoteScreen"
|
||||
headerMode="float"
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<VoteStack.Screen
|
||||
name="VoteScreen"
|
||||
component={VoteScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: "VoteScreen",
|
||||
headerLeft: openDrawer
|
||||
};
|
||||
}}
|
||||
/>
|
||||
</VoteStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
||||
const ClubStack = createStackNavigator();
|
||||
|
||||
function ClubStackComponent() {
|
||||
|
@ -341,6 +367,10 @@ export default function DrawerNavigator() {
|
|||
name="ClubListScreen"
|
||||
component={ClubStackComponent}
|
||||
/>
|
||||
<Drawer.Screen
|
||||
name="VoteScreen"
|
||||
component={VoteStackComponent}
|
||||
/>
|
||||
</Drawer.Navigator>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ class ClubListScreen extends React.Component<Props, State> {
|
|||
* @return {*}
|
||||
*/
|
||||
getHeaderButtons = () => {
|
||||
const onPress = () => this.props.navigation.navigate( "ClubAboutScreen");
|
||||
const onPress = () => this.props.navigation.navigate("ClubAboutScreen");
|
||||
return <HeaderButton icon={'information'} onPress={onPress}/>;
|
||||
};
|
||||
|
||||
|
@ -91,11 +91,11 @@ class ClubListScreen extends React.Component<Props, State> {
|
|||
itemLayout = (data, index) => ({length: LIST_ITEM_HEIGHT, offset: LIST_ITEM_HEIGHT * index, index});
|
||||
|
||||
getScreen = (data: Object) => {
|
||||
this.categories = data.categories;
|
||||
this.categories = data[0].categories;
|
||||
return (
|
||||
//$FlowFixMe
|
||||
<FlatList
|
||||
data={data.clubs}
|
||||
data={data[0].clubs}
|
||||
keyExtractor={this.keyExtractor}
|
||||
renderItem={this.getRenderItem}
|
||||
ListHeaderComponent={this.getListHeader()}
|
||||
|
@ -193,7 +193,12 @@ class ClubListScreen extends React.Component<Props, State> {
|
|||
return (
|
||||
<AuthenticatedScreen
|
||||
{...this.props}
|
||||
link={'https://www.amicale-insat.fr/api/clubs/list'}
|
||||
links={[
|
||||
{
|
||||
link: 'clubs/list',
|
||||
mandatory: true,
|
||||
}
|
||||
]}
|
||||
renderFunction={this.getScreen}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -149,18 +149,18 @@ class LoginScreen extends React.Component<Props, State> {
|
|||
const title = i18n.t("loginScreen.errors.title");
|
||||
let message;
|
||||
switch (error) {
|
||||
case ERROR_TYPE.CONNECTION_ERROR:
|
||||
message = i18n.t("loginScreen.errors.connection");
|
||||
break;
|
||||
case ERROR_TYPE.BAD_CREDENTIALS:
|
||||
message = i18n.t("loginScreen.errors.credentials");
|
||||
break;
|
||||
case ERROR_TYPE.SAVE_TOKEN:
|
||||
message = i18n.t("loginScreen.errors.saveToken");
|
||||
break;
|
||||
case ERROR_TYPE.NO_CONSENT:
|
||||
message = i18n.t("loginScreen.errors.consent");
|
||||
break;
|
||||
case ERROR_TYPE.CONNECTION_ERROR:
|
||||
message = i18n.t("loginScreen.errors.connection");
|
||||
break;
|
||||
case ERROR_TYPE.SERVER_ERROR:
|
||||
message = "SERVER ERROR"; // TODO translate
|
||||
break;
|
||||
default:
|
||||
message = i18n.t("loginScreen.errors.unknown");
|
||||
break;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {FlatList, StyleSheet, View} from "react-native";
|
||||
import {FlatList, ScrollView, StyleSheet} from "react-native";
|
||||
import {Avatar, Button, Card, Divider, List, withTheme} from 'react-native-paper';
|
||||
import AuthenticatedScreen from "../../components/Amicale/AuthenticatedScreen";
|
||||
import {openBrowser} from "../../utils/WebBrowser";
|
||||
|
@ -28,16 +28,9 @@ class ProfileScreen extends React.Component<Props, State> {
|
|||
|
||||
data: Object;
|
||||
|
||||
flatListData: Array<Object>;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.colors = props.theme.colors;
|
||||
this.flatListData = [
|
||||
{id: '0'},
|
||||
{id: '1'},
|
||||
{id: '2'},
|
||||
]
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -47,44 +40,29 @@ class ProfileScreen extends React.Component<Props, State> {
|
|||
});
|
||||
}
|
||||
|
||||
showDisconnectDialog = () => this.setState({ dialogVisible: true });
|
||||
showDisconnectDialog = () => this.setState({dialogVisible: true});
|
||||
|
||||
hideDisconnectDialog = () => this.setState({ dialogVisible: false });
|
||||
hideDisconnectDialog = () => this.setState({dialogVisible: false});
|
||||
|
||||
getHeaderButtons() {
|
||||
return <HeaderButton icon={'logout'} onPress={this.showDisconnectDialog}/>;
|
||||
}
|
||||
|
||||
getScreen(data: Object) {
|
||||
this.data = data;
|
||||
getScreen = (data: Object) => {
|
||||
this.data = data[0];
|
||||
return (
|
||||
<View>
|
||||
<FlatList
|
||||
renderItem={item => this.getRenderItem(item)}
|
||||
keyExtractor={item => item.id}
|
||||
data={this.flatListData}
|
||||
/>
|
||||
<ScrollView>
|
||||
{this.getPersonalCard()}
|
||||
{this.getClubCard()}
|
||||
{this.getMembershipCar()}
|
||||
<LogoutDialog
|
||||
{...this.props}
|
||||
visible={this.state.dialogVisible}
|
||||
onDismiss={this.hideDisconnectDialog}
|
||||
/>
|
||||
</View>
|
||||
|
||||
</ScrollView>
|
||||
)
|
||||
}
|
||||
|
||||
getRenderItem({item}: Object): any {
|
||||
switch (item.id) {
|
||||
case '0':
|
||||
return this.getPersonalCard();
|
||||
case '1':
|
||||
return this.getClubCard();
|
||||
case '2':
|
||||
return this.getMembershipCar();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
getPersonalCard() {
|
||||
return (
|
||||
|
@ -232,8 +210,13 @@ class ProfileScreen extends React.Component<Props, State> {
|
|||
return (
|
||||
<AuthenticatedScreen
|
||||
{...this.props}
|
||||
link={'https://www.amicale-insat.fr/api/user/profile'}
|
||||
renderFunction={(data) => this.getScreen(data)}
|
||||
links={[
|
||||
{
|
||||
link: 'user/profile',
|
||||
mandatory: true,
|
||||
}
|
||||
]}
|
||||
renderFunction={this.getScreen}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
130
src/screens/Amicale/VoteScreen.js
Normal file
130
src/screens/Amicale/VoteScreen.js
Normal file
|
@ -0,0 +1,130 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {ScrollView, StyleSheet} from "react-native";
|
||||
import {Avatar, Card, Paragraph, withTheme} from 'react-native-paper';
|
||||
import AuthenticatedScreen from "../../components/Amicale/AuthenticatedScreen";
|
||||
|
||||
const ICON_AMICALE = require('../../../assets/amicale.png');
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
theme: Object,
|
||||
}
|
||||
|
||||
type State = {}
|
||||
|
||||
class VoteScreen extends React.Component<Props, State> {
|
||||
|
||||
state = {};
|
||||
|
||||
colors: Object;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.colors = props.theme.colors;
|
||||
}
|
||||
|
||||
getScreen = (data: Object) => {
|
||||
console.log(data);
|
||||
return (
|
||||
<ScrollView>
|
||||
{this.getTitleCard()}
|
||||
{this.getVoteCard()}
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
getTitleCard() {
|
||||
return (
|
||||
<Card style={styles.card}>
|
||||
<Card.Title
|
||||
title={"VOTE"}
|
||||
subtitle={"WHY"}
|
||||
left={(props) => <Avatar.Image
|
||||
{...props}
|
||||
source={ICON_AMICALE}
|
||||
style={styles.icon}
|
||||
/>}
|
||||
/>
|
||||
<Card.Content>
|
||||
<Paragraph>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus rhoncus porttitor
|
||||
suscipit. Quisque hendrerit, quam id vestibulum vestibulum, lorem nisi hendrerit nisi, a
|
||||
eleifend sapien diam ut elit. Curabitur sit amet vulputate lectus. Donec semper cursus sapien
|
||||
vel finibus.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
Sed et venenatis turpis. Fusce malesuada magna urna, sed vehicula sem luctus in. Vivamus
|
||||
faucibus vel eros a ultricies. In sed laoreet ante, luctus mattis tellus. Etiam vitae ipsum
|
||||
sagittis, consequat purus sed, blandit risus.
|
||||
</Paragraph>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
getVoteCard() {
|
||||
return (
|
||||
<Card style={styles.card}>
|
||||
<Card.Title
|
||||
title={"VOTE OPEN"}
|
||||
subtitle={"VALID UNTIL DATE END"}
|
||||
/>
|
||||
<Card.Content>
|
||||
<Paragraph>TEAM1</Paragraph>
|
||||
<Paragraph>TEAM2</Paragraph>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
getVoteResultCard() {
|
||||
return (
|
||||
<Card style={styles.card}>
|
||||
<Card.Title
|
||||
title={"VOTE RESULTS"}
|
||||
subtitle={"DATE END RESULTS"}
|
||||
/>
|
||||
<Card.Content>
|
||||
<Paragraph>TEAM1</Paragraph>
|
||||
<Paragraph>TEAM2</Paragraph>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
getEmptyVoteCard() {
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<AuthenticatedScreen
|
||||
{...this.props}
|
||||
links={[
|
||||
{
|
||||
link: 'elections/teams',
|
||||
mandatory: false,
|
||||
},
|
||||
{
|
||||
link: 'elections/dates',
|
||||
mandatory: true,
|
||||
},
|
||||
]}
|
||||
renderFunction={this.getScreen}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
card: {
|
||||
margin: 10,
|
||||
},
|
||||
icon: {
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
});
|
||||
|
||||
export default withTheme(VoteScreen);
|
Loading…
Reference in a new issue