diff --git a/src/components/Amicale/AuthenticatedScreen.tsx b/src/components/Amicale/AuthenticatedScreen.tsx
deleted file mode 100644
index 4232496..0000000
--- a/src/components/Amicale/AuthenticatedScreen.tsx
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (c) 2019 - 2020 Arnaud Vergnet.
- *
- * This file is part of Campus INSAT.
- *
- * Campus INSAT is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Campus INSAT is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Campus INSAT. If not, see .
- */
-
-import * as React from 'react';
-import { StackNavigationProp } from '@react-navigation/stack';
-import ConnectionManager from '../../managers/ConnectionManager';
-import { ERROR_TYPE } from '../../utils/WebData';
-import ErrorView from '../Screens/ErrorView';
-import BasicLoadingScreen from '../Screens/BasicLoadingScreen';
-import i18n from 'i18n-js';
-
-type PropsType = {
- navigation: StackNavigationProp;
- requests: Array<{
- link: string;
- params: object;
- mandatory: boolean;
- }>;
- renderFunction: (data: Array) => React.ReactNode;
- errorViewOverride?: Array<{
- errorCode: number;
- message: string;
- icon: string;
- showRetryButton: boolean;
- }> | null;
-};
-
-type StateType = {
- loading: boolean;
-};
-
-class AuthenticatedScreen extends React.Component, StateType> {
- static defaultProps = {
- errorViewOverride: null,
- };
-
- currentUserToken: string | null;
-
- connectionManager: ConnectionManager;
-
- errors: Array;
-
- fetchedData: Array;
-
- constructor(props: PropsType) {
- super(props);
- this.state = {
- loading: true,
- };
- this.currentUserToken = null;
- this.connectionManager = ConnectionManager.getInstance();
- props.navigation.addListener('focus', this.onScreenFocus);
- this.fetchedData = new Array(props.requests.length);
- this.errors = new Array(props.requests.length);
- }
-
- /**
- * Refreshes screen if user changed
- */
- onScreenFocus = () => {
- if (this.currentUserToken !== this.connectionManager.getToken()) {
- this.currentUserToken = this.connectionManager.getToken();
- this.fetchData();
- }
- };
-
- /**
- * Callback used when a request finishes, successfully or not.
- * Saves data and error code.
- * If the token is invalid, logout the user and open the login screen.
- * If the last request was received, stop the loading screen.
- *
- * @param data The data fetched from the server
- * @param index The index for the data
- * @param error The error code received
- */
- onRequestFinished(data: T | null, index: number, error?: number) {
- const { props } = this;
- if (index >= 0 && index < props.requests.length) {
- this.fetchedData[index] = data;
- this.errors[index] = error != null ? error : ERROR_TYPE.SUCCESS;
- }
- // Token expired, logout user
- if (error === ERROR_TYPE.BAD_TOKEN) {
- this.connectionManager.disconnect();
- }
-
- if (this.allRequestsFinished()) {
- this.setState({ loading: false });
- }
- }
-
- /**
- * Gets the error to render.
- * Non-mandatory requests are ignored.
- *
- *
- * @return {number} The error code or ERROR_TYPE.SUCCESS if no error was found
- */
- getError(): number {
- const { props } = this;
- for (let i = 0; i < this.errors.length; i += 1) {
- if (
- this.errors[i] !== ERROR_TYPE.SUCCESS &&
- props.requests[i].mandatory
- ) {
- return this.errors[i];
- }
- }
- return ERROR_TYPE.SUCCESS;
- }
-
- /**
- * Gets the error view to display in case of error
- *
- * @return {*}
- */
- getErrorRender() {
- const { props } = this;
- const errorCode = this.getError();
- let shouldOverride = false;
- let override = null;
- const overrideList = props.errorViewOverride;
- if (overrideList != null) {
- for (let i = 0; i < overrideList.length; i += 1) {
- if (overrideList[i].errorCode === errorCode) {
- shouldOverride = true;
- override = overrideList[i];
- break;
- }
- }
- }
-
- if (shouldOverride && override != null) {
- return (
-
- );
- }
- return (
-
- );
- }
-
- /**
- * Fetches the data from the server.
- *
- * If the user is not logged in errorCode is set to BAD_TOKEN and all requests fail.
- *
- * If the user is logged in, send all requests.
- */
- fetchData = () => {
- const { state, props } = this;
- if (!state.loading) {
- this.setState({ loading: true });
- }
-
- if (this.connectionManager.isLoggedIn()) {
- for (let i = 0; i < props.requests.length; i += 1) {
- this.connectionManager
- .authenticatedRequest(
- props.requests[i].link,
- props.requests[i].params
- )
- .then((response: T): void => this.onRequestFinished(response, i))
- .catch((error: number): void =>
- this.onRequestFinished(null, i, error)
- );
- }
- } else {
- for (let i = 0; i < props.requests.length; i += 1) {
- this.onRequestFinished(null, i, ERROR_TYPE.BAD_TOKEN);
- }
- }
- };
-
- /**
- * Checks if all requests finished processing
- *
- * @return {boolean} True if all finished
- */
- allRequestsFinished(): boolean {
- let finished = true;
- this.errors.forEach((error: number | null) => {
- if (error == null) {
- finished = false;
- }
- });
- return finished;
- }
-
- /**
- * Reloads the data, to be called using ref by parent components
- */
- reload() {
- this.fetchData();
- }
-
- render() {
- const { state, props } = this;
- if (state.loading) {
- return ;
- }
- if (this.getError() === ERROR_TYPE.SUCCESS) {
- return props.renderFunction(this.fetchedData);
- }
- return this.getErrorRender();
- }
-}
-
-export default AuthenticatedScreen;
diff --git a/src/components/Dialogs/ErrorDialog.tsx b/src/components/Dialogs/ErrorDialog.tsx
index 45ff687..3b4c4d1 100644
--- a/src/components/Dialogs/ErrorDialog.tsx
+++ b/src/components/Dialogs/ErrorDialog.tsx
@@ -39,7 +39,7 @@ function ErrorDialog(props: PropsType) {
visible={props.visible}
onDismiss={props.onDismiss}
title={i18n.t('errors.title')}
- message={getErrorMessage(props)}
+ message={getErrorMessage(props).message}
/>
);
}
diff --git a/src/constants/Urls.tsx b/src/constants/Urls.tsx
index 017ca4e..2058fa1 100644
--- a/src/constants/Urls.tsx
+++ b/src/constants/Urls.tsx
@@ -33,7 +33,7 @@ const APP_IMAGES_ENDPOINT = STUDENT_SERVER + '~amicale_app/images/';
export default {
amicale: {
- api: APP_ENDPOINT,
+ api: AMICALE_ENDPOINT,
resetPassword: AMICALE_SERVER + 'password/reset',
events: AMICALE_ENDPOINT + 'event/list',
},
diff --git a/src/managers/ConnectionManager.ts b/src/managers/ConnectionManager.ts
index 6961e11..ee11ff2 100644
--- a/src/managers/ConnectionManager.ts
+++ b/src/managers/ConnectionManager.ts
@@ -163,7 +163,9 @@ export default class ConnectionManager {
});
}
})
- .catch(reject);
+ .catch((err) => {
+ reject(err);
+ });
}
);
}
@@ -177,7 +179,7 @@ export default class ConnectionManager {
*/
async authenticatedRequest(
path: string,
- params: { [key: string]: any }
+ params?: { [key: string]: any }
): Promise {
return new Promise(
(
diff --git a/src/screens/Amicale/Clubs/ClubDisplayScreen.tsx b/src/screens/Amicale/Clubs/ClubDisplayScreen.tsx
index 50aefc9..65cd4b0 100644
--- a/src/screens/Amicale/Clubs/ClubDisplayScreen.tsx
+++ b/src/screens/Amicale/Clubs/ClubDisplayScreen.tsx
@@ -29,13 +29,13 @@ import {
} from 'react-native-paper';
import i18n from 'i18n-js';
import { StackNavigationProp } from '@react-navigation/stack';
-import AuthenticatedScreen from '../../../components/Amicale/AuthenticatedScreen';
import CustomHTML from '../../../components/Overrides/CustomHTML';
import { TAB_BAR_HEIGHT } from '../../../components/Tabbar/CustomTabBar';
import type { ClubCategoryType, ClubType } from './ClubListScreen';
-import { ERROR_TYPE } from '../../../utils/WebData';
import CollapsibleScrollView from '../../../components/Collapsible/CollapsibleScrollView';
import ImageGalleryButton from '../../../components/Media/ImageGalleryButton';
+import RequestScreen from '../../../components/Screens/RequestScreen';
+import ConnectionManager from '../../../managers/ConnectionManager';
type PropsType = {
navigation: StackNavigationProp;
@@ -49,6 +49,8 @@ type PropsType = {
theme: ReactNativePaper.Theme;
};
+type ResponseType = ClubType;
+
const AMICALE_MAIL = 'clubs@amicale-insat.fr';
const styles = StyleSheet.create({
@@ -88,7 +90,7 @@ const styles = StyleSheet.create({
* If called with clubId parameter, will fetch the information on the server
*/
class ClubDisplayScreen extends React.Component {
- displayData: ClubType | null;
+ displayData: ClubType | undefined;
categories: Array | null;
@@ -98,7 +100,7 @@ class ClubDisplayScreen extends React.Component {
constructor(props: PropsType) {
super(props);
- this.displayData = null;
+ this.displayData = undefined;
this.categories = null;
this.clubId = props.route.params?.clubId ? props.route.params.clubId : 0;
this.shouldFetchData = true;
@@ -236,9 +238,8 @@ class ClubDisplayScreen extends React.Component {
);
}
- getScreen = (response: Array) => {
- let data: ClubType | null = response[0];
- if (data != null) {
+ getScreen = (data: ResponseType | undefined) => {
+ if (data) {
this.updateHeaderTitle(data);
return (
@@ -264,7 +265,7 @@ class ClubDisplayScreen extends React.Component {
);
}
- return null;
+ return ;
};
/**
@@ -278,31 +279,20 @@ class ClubDisplayScreen extends React.Component {
}
render() {
- const { props } = this;
if (this.shouldFetchData) {
return (
-
+ ConnectionManager.getInstance().authenticatedRequest(
+ 'clubs/info',
+ { id: this.clubId }
+ )
+ }
+ render={this.getScreen}
/>
);
}
- return this.getScreen([this.displayData]);
+ return this.getScreen(this.displayData);
}
}
diff --git a/src/screens/Amicale/Clubs/ClubListScreen.tsx b/src/screens/Amicale/Clubs/ClubListScreen.tsx
index 886a11a..7bf8a76 100644
--- a/src/screens/Amicale/Clubs/ClubListScreen.tsx
+++ b/src/screens/Amicale/Clubs/ClubListScreen.tsx
@@ -22,7 +22,6 @@ import { Platform } from 'react-native';
import { Searchbar } from 'react-native-paper';
import i18n from 'i18n-js';
import { StackNavigationProp } from '@react-navigation/stack';
-import AuthenticatedScreen from '../../../components/Amicale/AuthenticatedScreen';
import ClubListItem from '../../../components/Lists/Clubs/ClubListItem';
import {
isItemInCategoryFilter,
@@ -32,7 +31,8 @@ import ClubListHeader from '../../../components/Lists/Clubs/ClubListHeader';
import MaterialHeaderButtons, {
Item,
} from '../../../components/Overrides/CustomHeaderButton';
-import CollapsibleFlatList from '../../../components/Collapsible/CollapsibleFlatList';
+import ConnectionManager from '../../../managers/ConnectionManager';
+import WebSectionList from '../../../components/Screens/WebSectionList';
export type ClubCategoryType = {
id: number;
@@ -58,6 +58,11 @@ type StateType = {
currentSearchString: string;
};
+type ResponseType = {
+ categories: Array;
+ clubs: Array;
+};
+
const LIST_ITEM_HEIGHT = 96;
class ClubListScreen extends React.Component {
@@ -146,30 +151,13 @@ class ClubListScreen extends React.Component {
);
};
- getScreen = (
- data: Array<{
- categories: Array;
- clubs: Array;
- } | null>
- ) => {
- let categoryList: Array = [];
- let clubList: Array = [];
- if (data[0] != null) {
- categoryList = data[0].categories;
- clubList = data[0].clubs;
+ createDataset = (data: ResponseType | undefined) => {
+ if (data) {
+ this.categories = data?.categories;
+ return [{ title: '', data: data.clubs }];
+ } else {
+ return [{ title: '', data: [] }];
}
- this.categories = categoryList;
- return (
-
- );
};
/**
@@ -177,15 +165,19 @@ class ClubListScreen extends React.Component {
*
* @returns {*}
*/
- getListHeader() {
+ getListHeader(data: ResponseType | undefined) {
const { state } = this;
- return (
-
- );
+ if (data) {
+ return (
+
+ );
+ } else {
+ return null;
+ }
}
/**
@@ -223,15 +215,6 @@ class ClubListScreen extends React.Component {
keyExtractor = (item: ClubType): string => item.id.toString();
- itemLayout = (
- _data: Array | null | undefined,
- index: number
- ): { length: number; offset: number; index: number } => ({
- length: LIST_ITEM_HEIGHT,
- offset: LIST_ITEM_HEIGHT * index,
- index,
- });
-
/**
* Updates the search string and category filter, saving them to the State.
*
@@ -282,18 +265,20 @@ class ClubListScreen extends React.Component {
}
render() {
- const { props } = this;
return (
-
+ ConnectionManager.getInstance().authenticatedRequest(
+ 'clubs/list'
+ )
+ }
+ createDataset={this.createDataset}
+ keyExtractor={this.keyExtractor}
+ renderItem={this.getRenderItem}
+ renderListHeaderComponent={(data) => this.getListHeader(data)}
+ // Performance props, see https://reactnative.dev/docs/optimizing-flatlist-configuration
+ removeClippedSubviews={true}
+ itemHeight={LIST_ITEM_HEIGHT}
/>
);
}
diff --git a/src/screens/Amicale/Equipment/EquipmentListScreen.tsx b/src/screens/Amicale/Equipment/EquipmentListScreen.tsx
index 54d5b98..7c51e7a 100644
--- a/src/screens/Amicale/Equipment/EquipmentListScreen.tsx
+++ b/src/screens/Amicale/Equipment/EquipmentListScreen.tsx
@@ -22,13 +22,14 @@ import { StyleSheet, View } from 'react-native';
import { Button } from 'react-native-paper';
import { StackNavigationProp } from '@react-navigation/stack';
import i18n from 'i18n-js';
-import AuthenticatedScreen from '../../../components/Amicale/AuthenticatedScreen';
import EquipmentListItem from '../../../components/Lists/Equipment/EquipmentListItem';
import MascotPopup from '../../../components/Mascot/MascotPopup';
import { MASCOT_STYLE } from '../../../components/Mascot/Mascot';
import AsyncStorageManager from '../../../managers/AsyncStorageManager';
-import CollapsibleFlatList from '../../../components/Collapsible/CollapsibleFlatList';
import GENERAL_STYLES from '../../../constants/Styles';
+import ConnectionManager from '../../../managers/ConnectionManager';
+import { ApiRejectType } from '../../../utils/WebData';
+import WebSectionList from '../../../components/Screens/WebSectionList';
type PropsType = {
navigation: StackNavigationProp;
@@ -52,6 +53,11 @@ export type RentedDeviceType = {
end: string;
};
+type ResponseType = {
+ devices: Array;
+ locations?: Array;
+};
+
const LIST_ITEM_HEIGHT = 64;
const styles = StyleSheet.create({
@@ -65,10 +71,6 @@ const styles = StyleSheet.create({
class EquipmentListScreen extends React.Component {
userRents: null | Array;
- authRef: { current: null | AuthenticatedScreen };
-
- canRefresh: boolean;
-
constructor(props: PropsType) {
super(props);
this.userRents = null;
@@ -77,22 +79,8 @@ class EquipmentListScreen extends React.Component {
AsyncStorageManager.PREFERENCES.equipmentShowMascot.key
),
};
- this.canRefresh = false;
- this.authRef = React.createRef();
- props.navigation.addListener('focus', this.onScreenFocus);
}
- onScreenFocus = () => {
- if (
- this.canRefresh &&
- this.authRef.current &&
- this.authRef.current.reload
- ) {
- this.authRef.current.reload();
- }
- this.canRefresh = true;
- };
-
getRenderItem = ({ item }: { item: DeviceType }) => {
const { navigation } = this.props;
return (
@@ -139,37 +127,17 @@ class EquipmentListScreen extends React.Component {
keyExtractor = (item: DeviceType): string => item.id.toString();
- /**
- * Gets the main screen component with the fetched data
- *
- * @param data The data fetched from the server
- * @returns {*}
- */
- getScreen = (
- data: Array<
- | { devices: Array }
- | { locations: Array }
- | null
- >
- ) => {
- const [allDevices, userRents] = data;
- if (userRents) {
- this.userRents = (userRents as {
- locations: Array;
- }).locations;
+ createDataset = (data: ResponseType | undefined) => {
+ if (data) {
+ const userRents = data.locations;
+
+ if (userRents) {
+ this.userRents = userRents;
+ }
+ return [{ title: '', data: data.devices }];
+ } else {
+ return [{ title: '', data: [] }];
}
- return (
- }).devices
- : null
- }
- />
- );
};
showMascotDialog = () => {
@@ -184,26 +152,46 @@ class EquipmentListScreen extends React.Component {
this.setState({ mascotDialogVisible: false });
};
+ request = () => {
+ return new Promise(
+ (
+ resolve: (data: ResponseType) => void,
+ reject: (error: ApiRejectType) => void
+ ) => {
+ ConnectionManager.getInstance()
+ .authenticatedRequest<{ devices: Array }>('location/all')
+ .then((devicesData) => {
+ ConnectionManager.getInstance()
+ .authenticatedRequest<{
+ locations: Array;
+ }>('location/my')
+ .then((rentsData) => {
+ resolve({
+ devices: devicesData.devices,
+ locations: rentsData.locations,
+ });
+ })
+ .catch(() =>
+ resolve({
+ devices: devicesData.devices,
+ })
+ );
+ })
+ .catch(reject);
+ }
+ );
+ };
+
render() {
- const { props, state } = this;
+ const { state } = this;
return (
- this.getListHeader()}
/>
{
this.onInputChange(false, value);
};
props.navigation.addListener('focus', this.onScreenFocus);
+ // TODO remove
this.state = {
- email: '',
- password: '',
+ email: 'vergnet@etud.insa-toulouse.fr',
+ password: 'IGtt25ùj',
isEmailValidated: false,
isPasswordValidated: false,
loading: false,
dialogVisible: false,
- dialogError: REQUEST_STATUS.SUCCESS,
+ dialogError: { status: REQUEST_STATUS.SUCCESS },
mascotDialogVisible: AsyncStorageManager.getBool(
AsyncStorageManager.PREFERENCES.loginShowMascot.key
),
@@ -338,9 +339,11 @@ class LoginScreen extends React.Component {
* @param error The error given by the login request
*/
showErrorDialog = (error: ApiRejectType) => {
+ console.log(error);
+
this.setState({
dialogVisible: true,
- dialogError: error.status,
+ dialogError: error,
});
};
@@ -460,7 +463,8 @@ class LoginScreen extends React.Component {
diff --git a/src/screens/Amicale/ProfileScreen.tsx b/src/screens/Amicale/ProfileScreen.tsx
index 4d533e5..c329767 100644
--- a/src/screens/Amicale/ProfileScreen.tsx
+++ b/src/screens/Amicale/ProfileScreen.tsx
@@ -30,7 +30,6 @@ import {
} from 'react-native-paper';
import i18n from 'i18n-js';
import { StackNavigationProp } from '@react-navigation/stack';
-import AuthenticatedScreen from '../../components/Amicale/AuthenticatedScreen';
import LogoutDialog from '../../components/Amicale/LogoutDialog';
import MaterialHeaderButtons, {
Item,
@@ -42,6 +41,8 @@ import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatLis
import type { ServiceItemType } from '../../managers/ServicesManager';
import GENERAL_STYLES from '../../constants/Styles';
import Urls from '../../constants/Urls';
+import RequestScreen from '../../components/Screens/RequestScreen';
+import ConnectionManager from '../../managers/ConnectionManager';
type PropsType = {
navigation: StackNavigationProp;
@@ -89,7 +90,7 @@ const styles = StyleSheet.create({
});
class ProfileScreen extends React.Component {
- data: ProfileDataType | null;
+ data: ProfileDataType | undefined;
flatListData: Array<{ id: string }>;
@@ -97,7 +98,7 @@ class ProfileScreen extends React.Component {
constructor(props: PropsType) {
super(props);
- this.data = null;
+ this.data = undefined;
this.flatListData = [{ id: '0' }, { id: '1' }, { id: '2' }, { id: '3' }];
const services = new ServicesManager(props.navigation);
this.amicaleDataset = services.getAmicaleServices([SERVICES_KEY.PROFILE]);
@@ -134,21 +135,25 @@ class ProfileScreen extends React.Component {
* @param data The data fetched from the server
* @returns {*}
*/
- getScreen = (data: Array) => {
+ getScreen = (data: ProfileDataType | undefined) => {
const { dialogVisible } = this.state;
- this.data = data[0];
- return (
-
-
-
-
- );
+ if (data) {
+ this.data = data;
+ return (
+
+
+
+
+ );
+ } else {
+ return ;
+ }
};
getRenderItem = ({ item }: { item: { id: string } }) => {
@@ -482,18 +487,12 @@ class ProfileScreen extends React.Component {
}
render() {
- const { navigation } = this.props;
return (
-
+ request={() =>
+ ConnectionManager.getInstance().authenticatedRequest('user/profile')
+ }
+ render={this.getScreen}
/>
);
}
diff --git a/src/screens/Amicale/VoteScreen.tsx b/src/screens/Amicale/VoteScreen.tsx
index e28b951..5e546e2 100644
--- a/src/screens/Amicale/VoteScreen.tsx
+++ b/src/screens/Amicale/VoteScreen.tsx
@@ -18,11 +18,9 @@
*/
import * as React from 'react';
-import { RefreshControl, StyleSheet, View } from 'react-native';
-import { StackNavigationProp } from '@react-navigation/stack';
+import { StyleSheet, View } from 'react-native';
import i18n from 'i18n-js';
import { Button } from 'react-native-paper';
-import AuthenticatedScreen from '../../components/Amicale/AuthenticatedScreen';
import { getTimeOnlyString, stringToDate } from '../../utils/Planning';
import VoteTease from '../../components/Amicale/Vote/VoteTease';
import VoteSelect from '../../components/Amicale/Vote/VoteSelect';
@@ -32,8 +30,11 @@ import { MASCOT_STYLE } from '../../components/Mascot/Mascot';
import MascotPopup from '../../components/Mascot/MascotPopup';
import AsyncStorageManager from '../../managers/AsyncStorageManager';
import VoteNotAvailable from '../../components/Amicale/Vote/VoteNotAvailable';
-import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatList';
import GENERAL_STYLES from '../../constants/Styles';
+import ConnectionManager from '../../managers/ConnectionManager';
+import WebSectionList, {
+ SectionListDataType,
+} from '../../components/Screens/WebSectionList';
export type VoteTeamType = {
id: number;
@@ -60,6 +61,11 @@ type VoteDatesObjectType = {
date_result_end: Date;
};
+type ResponseType = {
+ teams?: TeamResponseType;
+ dates?: VoteDatesStringType;
+};
+
// const FAKE_DATE = {
// "date_begin": "2020-08-19 15:50",
// "date_end": "2020-08-19 15:50",
@@ -108,11 +114,7 @@ type VoteDatesObjectType = {
// ],
// };
-const MIN_REFRESH_TIME = 5 * 1000;
-
-type PropsType = {
- navigation: StackNavigationProp;
-};
+type PropsType = {};
type StateType = {
hasVoted: boolean;
@@ -135,23 +137,21 @@ export default class VoteScreen extends React.Component {
hasVoted: boolean;
- datesString: null | VoteDatesStringType;
+ datesString: undefined | VoteDatesStringType;
- dates: null | VoteDatesObjectType;
+ dates: undefined | VoteDatesObjectType;
today: Date;
- mainFlatListData: Array<{ key: string }>;
+ mainFlatListData: SectionListDataType<{ key: string }>;
- lastRefresh: Date | null;
-
- authRef: { current: null | AuthenticatedScreen };
+ refreshData: () => void;
constructor(props: PropsType) {
super(props);
this.teams = [];
- this.datesString = null;
- this.dates = null;
+ this.datesString = undefined;
+ this.dates = undefined;
this.state = {
hasVoted: false,
mascotDialogVisible: AsyncStorageManager.getBool(
@@ -160,9 +160,10 @@ export default class VoteScreen extends React.Component {
};
this.hasVoted = false;
this.today = new Date();
- this.authRef = React.createRef();
- this.lastRefresh = null;
- this.mainFlatListData = [{ key: 'main' }, { key: 'info' }];
+ this.refreshData = () => undefined;
+ this.mainFlatListData = [
+ { title: '', data: [{ key: 'main' }, { key: 'info' }] },
+ ];
}
/**
@@ -201,37 +202,32 @@ export default class VoteScreen extends React.Component {
return this.getContent();
};
- getScreen = (data: Array) => {
- const { state } = this;
+ createDataset = (
+ data: ResponseType | undefined,
+ _loading: boolean,
+ _lastRefreshDate: Date | undefined,
+ refreshData: () => void
+ ) => {
// data[0] = FAKE_TEAMS2;
// data[1] = FAKE_DATE;
- this.lastRefresh = new Date();
+ this.refreshData = refreshData;
+ if (data) {
+ const { teams, dates } = data;
- const teams = data[0] as TeamResponseType | null;
- const dateStrings = data[1] as VoteDatesStringType | null;
+ if (dates && dates.date_begin == null) {
+ this.datesString = undefined;
+ } else {
+ this.datesString = dates;
+ }
- if (dateStrings != null && dateStrings.date_begin == null) {
- this.datesString = null;
- } else {
- this.datesString = dateStrings;
+ if (teams) {
+ this.teams = teams.teams;
+ this.hasVoted = teams.has_voted;
+ }
+
+ this.generateDateObject();
}
-
- if (teams != null) {
- this.teams = teams.teams;
- this.hasVoted = teams.has_voted;
- }
-
- this.generateDateObject();
- return (
-
- }
- extraData={state.hasVoted.toString()}
- renderItem={this.getMainRenderItem}
- />
- );
+ return this.mainFlatListData;
};
getContent() {
@@ -261,7 +257,7 @@ export default class VoteScreen extends React.Component {
);
}
@@ -327,23 +323,6 @@ export default class VoteScreen extends React.Component {
);
}
- /**
- * Reloads vote data if last refresh delta is smaller than the minimum refresh time
- */
- reloadData = () => {
- let canRefresh;
- const { lastRefresh } = this;
- if (lastRefresh != null) {
- canRefresh =
- new Date().getTime() - lastRefresh.getTime() > MIN_REFRESH_TIME;
- } else {
- canRefresh = true;
- }
- if (canRefresh && this.authRef.current != null) {
- this.authRef.current.reload();
- }
- };
-
showMascotDialog = () => {
this.setState({ mascotDialogVisible: true });
};
@@ -403,13 +382,36 @@ export default class VoteScreen extends React.Component {
date_result_end: dateResultEnd,
};
} else {
- this.dates = null;
+ this.dates = undefined;
}
} else {
- this.dates = null;
+ this.dates = undefined;
}
}
+ request = () => {
+ return new Promise((resolve: (data: ResponseType) => void) => {
+ ConnectionManager.getInstance()
+ .authenticatedRequest('elections/dates')
+ .then((datesData) => {
+ ConnectionManager.getInstance()
+ .authenticatedRequest('elections/teams')
+ .then((teamsData) => {
+ resolve({
+ dates: datesData,
+ teams: teamsData,
+ });
+ })
+ .catch(() =>
+ resolve({
+ dates: datesData,
+ })
+ );
+ })
+ .catch(() => resolve({}));
+ });
+ };
+
/**
* Renders the authenticated screen.
*
@@ -418,25 +420,14 @@ export default class VoteScreen extends React.Component {
* @returns {*}
*/
render() {
- const { props, state } = this;
+ const { state } = this;
return (
-
- navigation={props.navigation}
- ref={this.authRef}
- requests={[
- {
- link: 'elections/teams',
- params: {},
- mandatory: false,
- },
- {
- link: 'elections/dates',
- params: {},
- mandatory: false,
- },
- ]}
- renderFunction={this.getScreen}
+
= {
- error: number;
- data: T;
+ status: REQUEST_STATUS;
+ error?: API_REQUEST_CODES;
+ data?: T;
};
export type ApiRejectType = {
@@ -87,6 +88,8 @@ export async function apiRequest(
if (params != null) {
requestParams = { ...params };
}
+ console.log(Urls.amicale.api + path);
+
fetch(Urls.amicale.api + path, {
method,
headers: new Headers({
@@ -95,12 +98,20 @@ export async function apiRequest(
}),
body: JSON.stringify(requestParams),
})
- .then(
- async (response: Response): Promise> =>
- response.json()
- )
+ .then((response: Response) => {
+ const status = response.status;
+ if (status === REQUEST_STATUS.SUCCESS) {
+ return response.json().then(
+ (data): ApiResponseType => {
+ return { status: status, error: data.error, data: data.data };
+ }
+ );
+ } else {
+ return { status: status };
+ }
+ })
.then((response: ApiResponseType) => {
- if (isApiResponseValid(response)) {
+ if (isApiResponseValid(response) && response.data) {
if (response.error === API_REQUEST_CODES.SUCCESS) {
resolve(response.data);
} else {
@@ -111,15 +122,15 @@ export async function apiRequest(
}
} else {
reject({
- status: REQUEST_STATUS.SERVER_ERROR,
+ status: response.status,
});
}
})
- .catch(() =>
+ .catch(() => {
reject({
- status: REQUEST_STATUS.SERVER_ERROR,
- })
- );
+ status: REQUEST_STATUS.CONNECTION_ERROR,
+ });
+ });
}
);
}