forked from vergnet/application-amicale
Update utility files to use TypeScript
This commit is contained in:
parent
375fc8b971
commit
18ec6e0a59
22 changed files with 318 additions and 268 deletions
16
package-lock.json
generated
16
package-lock.json
generated
|
@ -2501,6 +2501,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.36.tgz",
|
"resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.36.tgz",
|
||||||
"integrity": "sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ=="
|
"integrity": "sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ=="
|
||||||
},
|
},
|
||||||
|
"@types/i18n-js": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/i18n-js/-/i18n-js-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-GiZzazvxQ5j+EA4Zf4MtDsSaokAR/gW7FxxTlHi2p2xKFUhwAUT0B/MB8WL77P1TcqAO3MefWorFFyZS8F7s0Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/istanbul-lib-coverage": {
|
"@types/istanbul-lib-coverage": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
|
||||||
|
@ -2602,6 +2608,16 @@
|
||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/react-native-vector-icons": {
|
||||||
|
"version": "6.4.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.6.tgz",
|
||||||
|
"integrity": "sha512-lAyxNfMd5L1xZvXWsGcJmNegDf61TAp40uL6ashNNWj9W3IrDJO59L9+9inh0Y2MsEZpLTdxzVU8Unb4/0FQng==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/react-test-renderer": {
|
"@types/react-test-renderer": {
|
||||||
"version": "16.9.3",
|
"version": "16.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-16.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-16.9.3.tgz",
|
||||||
|
|
|
@ -66,6 +66,8 @@
|
||||||
"@babel/core": "^7.11.0",
|
"@babel/core": "^7.11.0",
|
||||||
"@babel/runtime": "^7.11.0",
|
"@babel/runtime": "^7.11.0",
|
||||||
"@react-native-community/eslint-config": "^1.1.0",
|
"@react-native-community/eslint-config": "^1.1.0",
|
||||||
|
"@types/i18n-js": "^3.0.3",
|
||||||
|
"@types/react-native-vector-icons": "^6.4.6",
|
||||||
"@types/jest": "^25.2.3",
|
"@types/jest": "^25.2.3",
|
||||||
"@types/react-native": "^0.63.2",
|
"@types/react-native": "^0.63.2",
|
||||||
"@types/react-test-renderer": "^16.9.2",
|
"@types/react-test-renderer": "^16.9.2",
|
||||||
|
|
|
@ -17,10 +17,7 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import type {ProxiwashMachineType} from '../screens/Proxiwash/ProxiwashScreen';
|
import type {ProxiwashMachineType} from '../screens/Proxiwash/ProxiwashScreen';
|
||||||
import type {CustomThemeType} from './ThemeManager';
|
|
||||||
import type {RuFoodCategoryType} from '../screens/Services/SelfMenuScreen';
|
import type {RuFoodCategoryType} from '../screens/Services/SelfMenuScreen';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,8 +54,9 @@ export default class AprilFoolsManager {
|
||||||
* @returns {ThemeManager}
|
* @returns {ThemeManager}
|
||||||
*/
|
*/
|
||||||
static getInstance(): AprilFoolsManager {
|
static getInstance(): AprilFoolsManager {
|
||||||
if (AprilFoolsManager.instance == null)
|
if (AprilFoolsManager.instance == null) {
|
||||||
AprilFoolsManager.instance = new AprilFoolsManager();
|
AprilFoolsManager.instance = new AprilFoolsManager();
|
||||||
|
}
|
||||||
return AprilFoolsManager.instance;
|
return AprilFoolsManager.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +128,9 @@ export default class AprilFoolsManager {
|
||||||
* @param currentTheme
|
* @param currentTheme
|
||||||
* @returns {{colors: {textDisabled: string, agendaDayTextColor: string, surface: string, background: string, dividerBackground: string, accent: string, agendaBackgroundColor: string, tabIcon: string, card: string, primary: string}}}
|
* @returns {{colors: {textDisabled: string, agendaDayTextColor: string, surface: string, background: string, dividerBackground: string, accent: string, agendaBackgroundColor: string, tabIcon: string, card: string, primary: string}}}
|
||||||
*/
|
*/
|
||||||
static getAprilFoolsTheme(currentTheme: CustomThemeType): CustomThemeType {
|
static getAprilFoolsTheme(
|
||||||
|
currentTheme: ReactNativePaper.Theme,
|
||||||
|
): ReactNativePaper.Theme {
|
||||||
return {
|
return {
|
||||||
...currentTheme,
|
...currentTheme,
|
||||||
colors: {
|
colors: {
|
|
@ -198,7 +198,7 @@ export default class AsyncStorageManager {
|
||||||
* @param key
|
* @param key
|
||||||
* @returns {{...}}
|
* @returns {{...}}
|
||||||
*/
|
*/
|
||||||
static getObject(key: string): object | Array<any> {
|
static getObject<T>(key: string): T {
|
||||||
return JSON.parse(AsyncStorageManager.getString(key));
|
return JSON.parse(AsyncStorageManager.getString(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import * as Keychain from 'react-native-keychain';
|
import * as Keychain from 'react-native-keychain';
|
||||||
import type {ApiDataLoginType, ApiGenericDataType} from '../utils/WebData';
|
import type {ApiDataLoginType} from '../utils/WebData';
|
||||||
import {apiRequest, ERROR_TYPE} from '../utils/WebData';
|
import {apiRequest, ERROR_TYPE} from '../utils/WebData';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,12 +40,10 @@ const AUTH_PATH = 'password';
|
||||||
export default class ConnectionManager {
|
export default class ConnectionManager {
|
||||||
static instance: ConnectionManager | null = null;
|
static instance: ConnectionManager | null = null;
|
||||||
|
|
||||||
#email: string;
|
private token: string | null;
|
||||||
|
|
||||||
#token: string | null;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.#token = null;
|
this.token = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,8 +52,9 @@ export default class ConnectionManager {
|
||||||
* @returns {ConnectionManager}
|
* @returns {ConnectionManager}
|
||||||
*/
|
*/
|
||||||
static getInstance(): ConnectionManager {
|
static getInstance(): ConnectionManager {
|
||||||
if (ConnectionManager.instance == null)
|
if (ConnectionManager.instance == null) {
|
||||||
ConnectionManager.instance = new ConnectionManager();
|
ConnectionManager.instance = new ConnectionManager();
|
||||||
|
}
|
||||||
return ConnectionManager.instance;
|
return ConnectionManager.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +64,7 @@ export default class ConnectionManager {
|
||||||
* @returns {string | null}
|
* @returns {string | null}
|
||||||
*/
|
*/
|
||||||
getToken(): string | null {
|
getToken(): string | null {
|
||||||
return this.#token;
|
return this.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,18 +76,17 @@ export default class ConnectionManager {
|
||||||
return new Promise(
|
return new Promise(
|
||||||
(resolve: (token: string) => void, reject: () => void) => {
|
(resolve: (token: string) => void, reject: () => void) => {
|
||||||
const token = this.getToken();
|
const token = this.getToken();
|
||||||
if (token != null) resolve(token);
|
if (token != null) {
|
||||||
else {
|
resolve(token);
|
||||||
|
} else {
|
||||||
Keychain.getInternetCredentials(SERVER_NAME)
|
Keychain.getInternetCredentials(SERVER_NAME)
|
||||||
.then((data: Keychain.UserCredentials | false) => {
|
.then((data: Keychain.UserCredentials | false) => {
|
||||||
if (
|
if (data && data.password != null) {
|
||||||
data != null &&
|
this.token = data.password;
|
||||||
data.password != null &&
|
resolve(this.token);
|
||||||
typeof data.password === 'string'
|
} else {
|
||||||
) {
|
reject();
|
||||||
this.#token = data.password;
|
}
|
||||||
resolve(this.#token);
|
|
||||||
} else reject();
|
|
||||||
})
|
})
|
||||||
.catch((): void => reject());
|
.catch((): void => reject());
|
||||||
}
|
}
|
||||||
|
@ -116,8 +114,7 @@ export default class ConnectionManager {
|
||||||
return new Promise((resolve: () => void, reject: () => void) => {
|
return new Promise((resolve: () => void, reject: () => void) => {
|
||||||
Keychain.setInternetCredentials(SERVER_NAME, 'token', token)
|
Keychain.setInternetCredentials(SERVER_NAME, 'token', token)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.#token = token;
|
this.token = token;
|
||||||
this.#email = email;
|
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch((): void => reject());
|
.catch((): void => reject());
|
||||||
|
@ -133,7 +130,7 @@ export default class ConnectionManager {
|
||||||
return new Promise((resolve: () => void, reject: () => void) => {
|
return new Promise((resolve: () => void, reject: () => void) => {
|
||||||
Keychain.resetInternetCredentials(SERVER_NAME)
|
Keychain.resetInternetCredentials(SERVER_NAME)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.#token = null;
|
this.token = null;
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch((): void => reject());
|
.catch((): void => reject());
|
||||||
|
@ -156,13 +153,15 @@ export default class ConnectionManager {
|
||||||
email,
|
email,
|
||||||
password,
|
password,
|
||||||
};
|
};
|
||||||
apiRequest(AUTH_PATH, 'POST', data)
|
apiRequest<ApiDataLoginType>(AUTH_PATH, 'POST', data)
|
||||||
.then((response: ApiDataLoginType) => {
|
.then((response: ApiDataLoginType) => {
|
||||||
if (response.token != null) {
|
if (response.token != null) {
|
||||||
this.saveLogin(email, response.token)
|
this.saveLogin(email, response.token)
|
||||||
.then((): void => resolve())
|
.then((): void => resolve())
|
||||||
.catch((): void => reject(ERROR_TYPE.TOKEN_SAVE));
|
.catch((): void => reject(ERROR_TYPE.TOKEN_SAVE));
|
||||||
} else reject(ERROR_TYPE.SERVER_ERROR);
|
} else {
|
||||||
|
reject(ERROR_TYPE.SERVER_ERROR);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((error: number): void => reject(error));
|
.catch((error: number): void => reject(error));
|
||||||
},
|
},
|
||||||
|
@ -176,24 +175,23 @@ export default class ConnectionManager {
|
||||||
* @param params
|
* @param params
|
||||||
* @returns Promise<ApiGenericDataType>
|
* @returns Promise<ApiGenericDataType>
|
||||||
*/
|
*/
|
||||||
async authenticatedRequest(
|
async authenticatedRequest<T>(
|
||||||
path: string,
|
path: string,
|
||||||
params: {...},
|
params: {[key: string]: any},
|
||||||
): Promise<ApiGenericDataType> {
|
): Promise<T> {
|
||||||
return new Promise(
|
return new Promise(
|
||||||
(
|
(resolve: (response: T) => void, reject: (error: number) => void) => {
|
||||||
resolve: (response: ApiGenericDataType) => void,
|
|
||||||
reject: (error: number) => void,
|
|
||||||
) => {
|
|
||||||
if (this.getToken() !== null) {
|
if (this.getToken() !== null) {
|
||||||
const data = {
|
const data = {
|
||||||
...params,
|
...params,
|
||||||
token: this.getToken(),
|
token: this.getToken(),
|
||||||
};
|
};
|
||||||
apiRequest(path, 'POST', data)
|
apiRequest<T>(path, 'POST', data)
|
||||||
.then((response: ApiGenericDataType): void => resolve(response))
|
.then((response: T): void => resolve(response))
|
||||||
.catch((error: number): void => reject(error));
|
.catch((error: number): void => reject(error));
|
||||||
} else reject(ERROR_TYPE.TOKEN_RETRIEVE);
|
} else {
|
||||||
|
reject(ERROR_TYPE.TOKEN_RETRIEVE);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -21,12 +21,12 @@
|
||||||
|
|
||||||
import type {ServiceItemType} from './ServicesManager';
|
import type {ServiceItemType} from './ServicesManager';
|
||||||
import ServicesManager from './ServicesManager';
|
import ServicesManager from './ServicesManager';
|
||||||
import {getSublistWithIds} from '../utils/Utils';
|
import {getSublistWithIds} from '../utils/Services';
|
||||||
import AsyncStorageManager from './AsyncStorageManager';
|
import AsyncStorageManager from './AsyncStorageManager';
|
||||||
|
|
||||||
export default class DashboardManager extends ServicesManager {
|
export default class DashboardManager extends ServicesManager {
|
||||||
getCurrentDashboard(): Array<ServiceItemType | null> {
|
getCurrentDashboard(): Array<ServiceItemType | null> {
|
||||||
const dashboardIdList = AsyncStorageManager.getObject(
|
const dashboardIdList = AsyncStorageManager.getObject<Array<string>>(
|
||||||
AsyncStorageManager.PREFERENCES.dashboardItems.key,
|
AsyncStorageManager.PREFERENCES.dashboardItems.key,
|
||||||
);
|
);
|
||||||
const allDatasets = [
|
const allDatasets = [
|
|
@ -17,8 +17,6 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,9 +26,9 @@ import i18n from 'i18n-js';
|
||||||
export default class DateManager {
|
export default class DateManager {
|
||||||
static instance: DateManager | null = null;
|
static instance: DateManager | null = null;
|
||||||
|
|
||||||
daysOfWeek = [];
|
daysOfWeek: Array<string> = [];
|
||||||
|
|
||||||
monthsOfYear = [];
|
monthsOfYear: Array<string> = [];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.daysOfWeek.push(i18n.t('date.daysOfWeek.sunday')); // 0 represents sunday
|
this.daysOfWeek.push(i18n.t('date.daysOfWeek.sunday')); // 0 represents sunday
|
||||||
|
@ -60,7 +58,9 @@ export default class DateManager {
|
||||||
* @returns {DateManager}
|
* @returns {DateManager}
|
||||||
*/
|
*/
|
||||||
static getInstance(): DateManager {
|
static getInstance(): DateManager {
|
||||||
if (DateManager.instance == null) DateManager.instance = new DateManager();
|
if (DateManager.instance == null) {
|
||||||
|
DateManager.instance = new DateManager();
|
||||||
|
}
|
||||||
return DateManager.instance;
|
return DateManager.instance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
import {StackNavigationProp} from '@react-navigation/stack';
|
import {StackNavigationProp} from '@react-navigation/stack';
|
||||||
import AvailableWebsites from '../constants/AvailableWebsites';
|
import AvailableWebsites from '../constants/AvailableWebsites';
|
||||||
|
@ -93,24 +91,24 @@ export const SERVICES_CATEGORIES_KEY = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ServiceItemType = {
|
export type ServiceItemType = {
|
||||||
key: string,
|
key: string;
|
||||||
title: string,
|
title: string;
|
||||||
subtitle: string,
|
subtitle: string;
|
||||||
image: string,
|
image: string;
|
||||||
onPress: () => void,
|
onPress: () => void;
|
||||||
badgeFunction?: (dashboard: FullDashboardType) => number,
|
badgeFunction?: (dashboard: FullDashboardType) => number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ServiceCategoryType = {
|
export type ServiceCategoryType = {
|
||||||
key: string,
|
key: string;
|
||||||
title: string,
|
title: string;
|
||||||
subtitle: string,
|
subtitle: string;
|
||||||
image: string | number,
|
image: string | number;
|
||||||
content: Array<ServiceItemType>,
|
content: Array<ServiceItemType>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class ServicesManager {
|
export default class ServicesManager {
|
||||||
navigation: StackNavigationProp;
|
navigation: StackNavigationProp<any>;
|
||||||
|
|
||||||
amicaleDataset: Array<ServiceItemType>;
|
amicaleDataset: Array<ServiceItemType>;
|
||||||
|
|
||||||
|
@ -122,7 +120,7 @@ export default class ServicesManager {
|
||||||
|
|
||||||
categoriesDataset: Array<ServiceCategoryType>;
|
categoriesDataset: Array<ServiceCategoryType>;
|
||||||
|
|
||||||
constructor(nav: StackNavigationProp) {
|
constructor(nav: StackNavigationProp<any>) {
|
||||||
this.navigation = nav;
|
this.navigation = nav;
|
||||||
this.amicaleDataset = [
|
this.amicaleDataset = [
|
||||||
{
|
{
|
||||||
|
@ -336,9 +334,11 @@ export default class ServicesManager {
|
||||||
* @returns {null}
|
* @returns {null}
|
||||||
*/
|
*/
|
||||||
onAmicaleServicePress(route: string) {
|
onAmicaleServicePress(route: string) {
|
||||||
if (ConnectionManager.getInstance().isLoggedIn())
|
if (ConnectionManager.getInstance().isLoggedIn()) {
|
||||||
this.navigation.navigate(route);
|
this.navigation.navigate(route);
|
||||||
else this.navigation.navigate('login', {nextScreen: route});
|
} else {
|
||||||
|
this.navigation.navigate('login', {nextScreen: route});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -348,8 +348,9 @@ export default class ServicesManager {
|
||||||
* @returns {Array<ServiceItemType>}
|
* @returns {Array<ServiceItemType>}
|
||||||
*/
|
*/
|
||||||
getAmicaleServices(excludedItems?: Array<string>): Array<ServiceItemType> {
|
getAmicaleServices(excludedItems?: Array<string>): Array<ServiceItemType> {
|
||||||
if (excludedItems != null)
|
if (excludedItems != null) {
|
||||||
return getStrippedServicesList(excludedItems, this.amicaleDataset);
|
return getStrippedServicesList(excludedItems, this.amicaleDataset);
|
||||||
|
}
|
||||||
return this.amicaleDataset;
|
return this.amicaleDataset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,8 +361,9 @@ export default class ServicesManager {
|
||||||
* @returns {Array<ServiceItemType>}
|
* @returns {Array<ServiceItemType>}
|
||||||
*/
|
*/
|
||||||
getStudentServices(excludedItems?: Array<string>): Array<ServiceItemType> {
|
getStudentServices(excludedItems?: Array<string>): Array<ServiceItemType> {
|
||||||
if (excludedItems != null)
|
if (excludedItems != null) {
|
||||||
return getStrippedServicesList(excludedItems, this.studentsDataset);
|
return getStrippedServicesList(excludedItems, this.studentsDataset);
|
||||||
|
}
|
||||||
return this.studentsDataset;
|
return this.studentsDataset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,8 +374,9 @@ export default class ServicesManager {
|
||||||
* @returns {Array<ServiceItemType>}
|
* @returns {Array<ServiceItemType>}
|
||||||
*/
|
*/
|
||||||
getINSAServices(excludedItems?: Array<string>): Array<ServiceItemType> {
|
getINSAServices(excludedItems?: Array<string>): Array<ServiceItemType> {
|
||||||
if (excludedItems != null)
|
if (excludedItems != null) {
|
||||||
return getStrippedServicesList(excludedItems, this.insaDataset);
|
return getStrippedServicesList(excludedItems, this.insaDataset);
|
||||||
|
}
|
||||||
return this.insaDataset;
|
return this.insaDataset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,8 +387,9 @@ export default class ServicesManager {
|
||||||
* @returns {Array<ServiceItemType>}
|
* @returns {Array<ServiceItemType>}
|
||||||
*/
|
*/
|
||||||
getSpecialServices(excludedItems?: Array<string>): Array<ServiceItemType> {
|
getSpecialServices(excludedItems?: Array<string>): Array<ServiceItemType> {
|
||||||
if (excludedItems != null)
|
if (excludedItems != null) {
|
||||||
return getStrippedServicesList(excludedItems, this.specialDataset);
|
return getStrippedServicesList(excludedItems, this.specialDataset);
|
||||||
|
}
|
||||||
return this.specialDataset;
|
return this.specialDataset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,8 +400,9 @@ export default class ServicesManager {
|
||||||
* @returns {Array<ServiceCategoryType>}
|
* @returns {Array<ServiceCategoryType>}
|
||||||
*/
|
*/
|
||||||
getCategories(excludedItems?: Array<string>): Array<ServiceCategoryType> {
|
getCategories(excludedItems?: Array<string>): Array<ServiceCategoryType> {
|
||||||
if (excludedItems != null)
|
if (excludedItems != null) {
|
||||||
return getStrippedServicesList(excludedItems, this.categoriesDataset);
|
return getStrippedServicesList(excludedItems, this.categoriesDataset);
|
||||||
|
}
|
||||||
return this.categoriesDataset;
|
return this.categoriesDataset;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,22 +17,12 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
import {NativeScrollEvent, NativeSyntheticEvent} from 'react-native';
|
||||||
|
|
||||||
const speedOffset = 5;
|
const speedOffset = 5;
|
||||||
|
|
||||||
type ListenerFunctionType = (shouldHide: boolean) => void;
|
type ListenerFunctionType = (shouldHide: boolean) => void;
|
||||||
|
|
||||||
export type OnScrollType = {
|
|
||||||
nativeEvent: {
|
|
||||||
contentInset: {bottom: number, left: number, right: number, top: number},
|
|
||||||
contentOffset: {x: number, y: number},
|
|
||||||
contentSize: {height: number, width: number},
|
|
||||||
layoutMeasurement: {height: number, width: number},
|
|
||||||
zoomScale: number,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to detect when to show or hide a component based on scrolling
|
* Class used to detect when to show or hide a component based on scrolling
|
||||||
*/
|
*/
|
||||||
|
@ -46,6 +36,7 @@ export default class AutoHideHandler {
|
||||||
constructor(startHidden: boolean) {
|
constructor(startHidden: boolean) {
|
||||||
this.listeners = [];
|
this.listeners = [];
|
||||||
this.isHidden = startHidden;
|
this.isHidden = startHidden;
|
||||||
|
this.lastOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,7 +75,7 @@ export default class AutoHideHandler {
|
||||||
*
|
*
|
||||||
* @param event The scroll event generated by the animated component onScroll prop
|
* @param event The scroll event generated by the animated component onScroll prop
|
||||||
*/
|
*/
|
||||||
onScroll(event: OnScrollType) {
|
onScroll(event: NativeSyntheticEvent<NativeScrollEvent>) {
|
||||||
const {nativeEvent} = event;
|
const {nativeEvent} = event;
|
||||||
const speed =
|
const speed =
|
||||||
nativeEvent.contentOffset.y < 0
|
nativeEvent.contentOffset.y < 0
|
|
@ -17,12 +17,20 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {useTheme} from 'react-native-paper';
|
import {useTheme} from 'react-native-paper';
|
||||||
import {createCollapsibleStack} from 'react-navigation-collapsible';
|
import {createCollapsibleStack} from 'react-navigation-collapsible';
|
||||||
import StackNavigator, {StackNavigationOptions} from '@react-navigation/stack';
|
import StackNavigator, {StackNavigationOptions} from '@react-navigation/stack';
|
||||||
|
import {StackNavigationState} from '@react-navigation/native';
|
||||||
|
import {StackNavigationEventMap} from '@react-navigation/stack/lib/typescript/src/types';
|
||||||
|
|
||||||
|
type StackNavigatorType = import('@react-navigation/native').TypedNavigator<
|
||||||
|
Record<string, object | undefined>,
|
||||||
|
StackNavigationState,
|
||||||
|
StackNavigationOptions,
|
||||||
|
StackNavigationEventMap,
|
||||||
|
typeof StackNavigator
|
||||||
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a navigation stack with the collapsible library, allowing the header to collapse on scroll.
|
* Creates a navigation stack with the collapsible library, allowing the header to collapse on scroll.
|
||||||
|
@ -40,18 +48,16 @@ import StackNavigator, {StackNavigationOptions} from '@react-navigation/stack';
|
||||||
* @param headerColor The color of the header. Uses default color if not specified
|
* @param headerColor The color of the header. Uses default color if not specified
|
||||||
* @returns {JSX.Element}
|
* @returns {JSX.Element}
|
||||||
*/
|
*/
|
||||||
export function createScreenCollapsibleStack(
|
export function CreateScreenCollapsibleStack(
|
||||||
name: string,
|
name: string,
|
||||||
Stack: StackNavigator,
|
Stack: StackNavigatorType,
|
||||||
// eslint-disable-next-line flowtype/no-weak-types
|
|
||||||
component: React.ComponentType<any>,
|
component: React.ComponentType<any>,
|
||||||
title: string,
|
title: string,
|
||||||
useNativeDriver?: boolean,
|
useNativeDriver: boolean = true,
|
||||||
options?: StackNavigationOptions,
|
options: StackNavigationOptions = {},
|
||||||
headerColor?: string,
|
headerColor?: string,
|
||||||
): React.Node {
|
) {
|
||||||
const {colors} = useTheme();
|
const {colors} = useTheme();
|
||||||
const screenOptions = options != null ? options : {};
|
|
||||||
return createCollapsibleStack(
|
return createCollapsibleStack(
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name={name}
|
name={name}
|
||||||
|
@ -61,12 +67,12 @@ export function createScreenCollapsibleStack(
|
||||||
headerStyle: {
|
headerStyle: {
|
||||||
backgroundColor: headerColor != null ? headerColor : colors.surface,
|
backgroundColor: headerColor != null ? headerColor : colors.surface,
|
||||||
},
|
},
|
||||||
...screenOptions,
|
...options,
|
||||||
}}
|
}}
|
||||||
/>,
|
/>,
|
||||||
{
|
{
|
||||||
collapsedColor: headerColor != null ? headerColor : colors.surface,
|
collapsedColor: headerColor != null ? headerColor : colors.surface,
|
||||||
useNativeDriver: useNativeDriver != null ? useNativeDriver : true, // native driver does not work with webview
|
useNativeDriver: useNativeDriver, // native driver does not work with webview
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -85,10 +91,9 @@ export function createScreenCollapsibleStack(
|
||||||
*/
|
*/
|
||||||
export function getWebsiteStack(
|
export function getWebsiteStack(
|
||||||
name: string,
|
name: string,
|
||||||
Stack: StackNavigator,
|
Stack: StackNavigatorType,
|
||||||
// eslint-disable-next-line flowtype/no-weak-types
|
|
||||||
component: React.ComponentType<any>,
|
component: React.ComponentType<any>,
|
||||||
title: string,
|
title: string,
|
||||||
): React.Node {
|
) {
|
||||||
return createScreenCollapsibleStack(name, Stack, component, title, false);
|
return CreateScreenCollapsibleStack(name, Stack, component, title, false);
|
||||||
}
|
}
|
|
@ -17,12 +17,9 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
import type {DeviceType} from '../screens/Amicale/Equipment/EquipmentListScreen';
|
import type {DeviceType} from '../screens/Amicale/Equipment/EquipmentListScreen';
|
||||||
import DateManager from '../managers/DateManager';
|
import DateManager from '../managers/DateManager';
|
||||||
import type {CustomThemeType} from '../managers/ThemeManager';
|
|
||||||
import type {MarkedDatesObjectType} from '../screens/Amicale/Equipment/EquipmentRentScreen';
|
import type {MarkedDatesObjectType} from '../screens/Amicale/Equipment/EquipmentRentScreen';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,10 +53,12 @@ export function isEquipmentAvailable(item: DeviceType): boolean {
|
||||||
let isAvailable = true;
|
let isAvailable = true;
|
||||||
const today = getCurrentDay();
|
const today = getCurrentDay();
|
||||||
const dates = item.booked_at;
|
const dates = item.booked_at;
|
||||||
dates.forEach((date: {begin: string, end: string}) => {
|
dates.forEach((date: {begin: string; end: string}) => {
|
||||||
const start = new Date(date.begin);
|
const start = new Date(date.begin);
|
||||||
const end = new Date(date.end);
|
const end = new Date(date.end);
|
||||||
if (!(today < start || today > end)) isAvailable = false;
|
if (!(today < start || today > end)) {
|
||||||
|
isAvailable = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return isAvailable;
|
return isAvailable;
|
||||||
}
|
}
|
||||||
|
@ -73,11 +72,13 @@ export function isEquipmentAvailable(item: DeviceType): boolean {
|
||||||
export function getFirstEquipmentAvailability(item: DeviceType): Date {
|
export function getFirstEquipmentAvailability(item: DeviceType): Date {
|
||||||
let firstAvailability = getCurrentDay();
|
let firstAvailability = getCurrentDay();
|
||||||
const dates = item.booked_at;
|
const dates = item.booked_at;
|
||||||
dates.forEach((date: {begin: string, end: string}) => {
|
dates.forEach((date: {begin: string; end: string}) => {
|
||||||
const start = new Date(date.begin);
|
const start = new Date(date.begin);
|
||||||
const end = new Date(date.end);
|
const end = new Date(date.end);
|
||||||
end.setDate(end.getDate() + 1);
|
end.setDate(end.getDate() + 1);
|
||||||
if (firstAvailability >= start) firstAvailability = end;
|
if (firstAvailability >= start) {
|
||||||
|
firstAvailability = end;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return firstAvailability;
|
return firstAvailability;
|
||||||
}
|
}
|
||||||
|
@ -93,23 +94,24 @@ export function getRelativeDateString(date: Date): string {
|
||||||
const monthDelta = date.getUTCMonth() - today.getUTCMonth();
|
const monthDelta = date.getUTCMonth() - today.getUTCMonth();
|
||||||
const dayDelta = date.getUTCDate() - today.getUTCDate();
|
const dayDelta = date.getUTCDate() - today.getUTCDate();
|
||||||
let translatedString = i18n.t('screens.equipment.today');
|
let translatedString = i18n.t('screens.equipment.today');
|
||||||
if (yearDelta > 0)
|
if (yearDelta > 0) {
|
||||||
translatedString = i18n.t('screens.equipment.otherYear', {
|
translatedString = i18n.t('screens.equipment.otherYear', {
|
||||||
date: date.getDate(),
|
date: date.getDate(),
|
||||||
month: DateManager.getInstance().getMonthsOfYear()[date.getMonth()],
|
month: DateManager.getInstance().getMonthsOfYear()[date.getMonth()],
|
||||||
year: date.getFullYear(),
|
year: date.getFullYear(),
|
||||||
});
|
});
|
||||||
else if (monthDelta > 0)
|
} else if (monthDelta > 0) {
|
||||||
translatedString = i18n.t('screens.equipment.otherMonth', {
|
translatedString = i18n.t('screens.equipment.otherMonth', {
|
||||||
date: date.getDate(),
|
date: date.getDate(),
|
||||||
month: DateManager.getInstance().getMonthsOfYear()[date.getMonth()],
|
month: DateManager.getInstance().getMonthsOfYear()[date.getMonth()],
|
||||||
});
|
});
|
||||||
else if (dayDelta > 1)
|
} else if (dayDelta > 1) {
|
||||||
translatedString = i18n.t('screens.equipment.thisMonth', {
|
translatedString = i18n.t('screens.equipment.thisMonth', {
|
||||||
date: date.getDate(),
|
date: date.getDate(),
|
||||||
});
|
});
|
||||||
else if (dayDelta === 1)
|
} else if (dayDelta === 1) {
|
||||||
translatedString = i18n.t('screens.equipment.tomorrow');
|
translatedString = i18n.t('screens.equipment.tomorrow');
|
||||||
|
}
|
||||||
|
|
||||||
return translatedString;
|
return translatedString;
|
||||||
}
|
}
|
||||||
|
@ -162,8 +164,11 @@ export function getValidRange(
|
||||||
(direction === 1 && date < limit) ||
|
(direction === 1 && date < limit) ||
|
||||||
(direction === -1 && date > limit)
|
(direction === -1 && date > limit)
|
||||||
) {
|
) {
|
||||||
if (direction === 1) validRange.push(getISODate(date));
|
if (direction === 1) {
|
||||||
else validRange.unshift(getISODate(date));
|
validRange.push(getISODate(date));
|
||||||
|
} else {
|
||||||
|
validRange.unshift(getISODate(date));
|
||||||
|
}
|
||||||
date.setDate(date.getDate() + direction);
|
date.setDate(date.getDate() + direction);
|
||||||
}
|
}
|
||||||
return validRange;
|
return validRange;
|
||||||
|
@ -180,17 +185,27 @@ export function getValidRange(
|
||||||
*/
|
*/
|
||||||
export function generateMarkedDates(
|
export function generateMarkedDates(
|
||||||
isSelection: boolean,
|
isSelection: boolean,
|
||||||
theme: CustomThemeType,
|
theme: ReactNativePaper.Theme,
|
||||||
range: Array<string>,
|
range: Array<string>,
|
||||||
): MarkedDatesObjectType {
|
): MarkedDatesObjectType {
|
||||||
const markedDates = {};
|
const markedDates: {
|
||||||
|
[key: string]: {
|
||||||
|
startingDay: boolean;
|
||||||
|
endingDay: boolean;
|
||||||
|
color: string;
|
||||||
|
};
|
||||||
|
} = {};
|
||||||
for (let i = 0; i < range.length; i += 1) {
|
for (let i = 0; i < range.length; i += 1) {
|
||||||
const isStart = i === 0;
|
const isStart = i === 0;
|
||||||
const isEnd = i === range.length - 1;
|
const isEnd = i === range.length - 1;
|
||||||
let color;
|
let color;
|
||||||
if (isSelection && (isStart || isEnd)) color = theme.colors.primary;
|
if (isSelection && (isStart || isEnd)) {
|
||||||
else if (isSelection) color = theme.colors.danger;
|
color = theme.colors.primary;
|
||||||
else color = theme.colors.textDisabled;
|
} else if (isSelection) {
|
||||||
|
color = theme.colors.danger;
|
||||||
|
} else {
|
||||||
|
color = theme.colors.textDisabled;
|
||||||
|
}
|
||||||
markedDates[range[i]] = {
|
markedDates[range[i]] = {
|
||||||
startingDay: isStart,
|
startingDay: isStart,
|
||||||
endingDay: isEnd,
|
endingDay: isEnd,
|
|
@ -17,8 +17,6 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import {stringToDate} from './Planning';
|
import {stringToDate} from './Planning';
|
||||||
import type {PlanningEventType} from './Planning';
|
import type {PlanningEventType} from './Planning';
|
||||||
|
|
||||||
|
@ -29,13 +27,15 @@ import type {PlanningEventType} from './Planning';
|
||||||
*/
|
*/
|
||||||
export function getTodayEventTimeLimit(): Date {
|
export function getTodayEventTimeLimit(): Date {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
if (now.getDay() === 4)
|
if (now.getDay() === 4) {
|
||||||
// Thursday
|
// Thursday
|
||||||
now.setHours(11, 30, 0);
|
now.setHours(11, 30, 0);
|
||||||
else if (now.getDay() === 6 || now.getDay() === 0)
|
} else if (now.getDay() === 6 || now.getDay() === 0) {
|
||||||
// Weekend
|
// Weekend
|
||||||
now.setHours(0, 0, 0);
|
now.setHours(0, 0, 0);
|
||||||
else now.setHours(17, 30, 0);
|
} else {
|
||||||
|
now.setHours(17, 30, 0);
|
||||||
|
}
|
||||||
return now;
|
return now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ export function getEventsAfterLimit(
|
||||||
events: Array<PlanningEventType>,
|
events: Array<PlanningEventType>,
|
||||||
limit: Date,
|
limit: Date,
|
||||||
): Array<PlanningEventType> {
|
): Array<PlanningEventType> {
|
||||||
const validEvents = [];
|
const validEvents: Array<PlanningEventType> = [];
|
||||||
events.forEach((event: PlanningEventType) => {
|
events.forEach((event: PlanningEventType) => {
|
||||||
const startDate = stringToDate(event.date_begin);
|
const startDate = stringToDate(event.date_begin);
|
||||||
if (startDate != null && startDate >= limit) {
|
if (startDate != null && startDate >= limit) {
|
||||||
|
@ -68,11 +68,13 @@ export function getEventsAfterLimit(
|
||||||
export function getFutureEvents(
|
export function getFutureEvents(
|
||||||
events: Array<PlanningEventType>,
|
events: Array<PlanningEventType>,
|
||||||
): Array<PlanningEventType> {
|
): Array<PlanningEventType> {
|
||||||
const validEvents = [];
|
const validEvents: Array<PlanningEventType> = [];
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
events.forEach((event: PlanningEventType) => {
|
events.forEach((event: PlanningEventType) => {
|
||||||
const startDate = stringToDate(event.date_begin);
|
const startDate = stringToDate(event.date_begin);
|
||||||
if (startDate != null && startDate > now) validEvents.push(event);
|
if (startDate != null && startDate > now) {
|
||||||
|
validEvents.push(event);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return validEvents;
|
return validEvents;
|
||||||
}
|
}
|
||||||
|
@ -92,8 +94,13 @@ export function getDisplayEvent(
|
||||||
events,
|
events,
|
||||||
getTodayEventTimeLimit(),
|
getTodayEventTimeLimit(),
|
||||||
);
|
);
|
||||||
if (eventsAfterLimit.length > 0) [displayEvent] = eventsAfterLimit;
|
if (eventsAfterLimit.length > 0) {
|
||||||
else [displayEvent] = events;
|
[displayEvent] = eventsAfterLimit;
|
||||||
} else if (events.length === 1) [displayEvent] = events;
|
} else {
|
||||||
|
[displayEvent] = events;
|
||||||
|
}
|
||||||
|
} else if (events.length === 1) {
|
||||||
|
[displayEvent] = events;
|
||||||
|
}
|
||||||
return displayEvent;
|
return displayEvent;
|
||||||
}
|
}
|
|
@ -17,8 +17,6 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
import * as RNLocalize from 'react-native-localize';
|
import * as RNLocalize from 'react-native-localize';
|
||||||
|
|
||||||
|
@ -28,9 +26,7 @@ import fr from '../../locales/fr.json';
|
||||||
const initLocales = () => {
|
const initLocales = () => {
|
||||||
i18n.fallbacks = true;
|
i18n.fallbacks = true;
|
||||||
i18n.translations = {fr, en};
|
i18n.translations = {fr, en};
|
||||||
i18n.locale = RNLocalize.findBestAvailableLanguage([
|
const bestLanguage = RNLocalize.findBestAvailableLanguage(['en', 'fr']);
|
||||||
'en',
|
i18n.locale = bestLanguage ? bestLanguage.languageTag : 'en';
|
||||||
'fr',
|
};
|
||||||
]).languageTag;
|
|
||||||
}
|
|
||||||
export default initLocales;
|
export default initLocales;
|
|
@ -17,8 +17,6 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
checkNotifications,
|
checkNotifications,
|
||||||
requestNotifications,
|
requestNotifications,
|
||||||
|
@ -41,12 +39,17 @@ const reminderIdFactor = 100;
|
||||||
export async function askPermissions(): Promise<void> {
|
export async function askPermissions(): Promise<void> {
|
||||||
return new Promise((resolve: () => void, reject: () => void) => {
|
return new Promise((resolve: () => void, reject: () => void) => {
|
||||||
checkNotifications().then(({status}: {status: string}) => {
|
checkNotifications().then(({status}: {status: string}) => {
|
||||||
if (status === RESULTS.GRANTED) resolve();
|
if (status === RESULTS.GRANTED) {
|
||||||
else if (status === RESULTS.BLOCKED) reject();
|
resolve();
|
||||||
else {
|
} else if (status === RESULTS.BLOCKED) {
|
||||||
requestNotifications().then((result: {status: string}) => {
|
reject();
|
||||||
if (result.status === RESULTS.GRANTED) resolve();
|
} else {
|
||||||
else reject();
|
requestNotifications([]).then((result: {status: string}) => {
|
||||||
|
if (result.status === RESULTS.GRANTED) {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
|
@ -17,18 +17,16 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
export type PlanningEventType = {
|
export type PlanningEventType = {
|
||||||
id: number,
|
id: number;
|
||||||
title: string,
|
title: string;
|
||||||
date_begin: string,
|
date_begin: string;
|
||||||
club: string,
|
club: string;
|
||||||
category_id: number,
|
category_id: number;
|
||||||
description: string,
|
description: string;
|
||||||
place: string,
|
place: string;
|
||||||
url: string,
|
url: string;
|
||||||
logo: string | null,
|
logo: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Regex used to check date string validity
|
// Regex used to check date string validity
|
||||||
|
@ -41,7 +39,7 @@ const dateRegExp = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/;
|
||||||
* @param dateString The string to check
|
* @param dateString The string to check
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
export function isEventDateStringFormatValid(dateString: ?string): boolean {
|
export function isEventDateStringFormatValid(dateString?: string): boolean {
|
||||||
return (
|
return (
|
||||||
dateString !== undefined &&
|
dateString !== undefined &&
|
||||||
dateString !== null &&
|
dateString !== null &&
|
||||||
|
@ -57,7 +55,7 @@ export function isEventDateStringFormatValid(dateString: ?string): boolean {
|
||||||
* @return {Date|null} The date object or null if the given string is invalid
|
* @return {Date|null} The date object or null if the given string is invalid
|
||||||
*/
|
*/
|
||||||
export function stringToDate(dateString: string): Date | null {
|
export function stringToDate(dateString: string): Date | null {
|
||||||
let date = new Date();
|
let date: Date | null = new Date();
|
||||||
if (isEventDateStringFormatValid(dateString)) {
|
if (isEventDateStringFormatValid(dateString)) {
|
||||||
const stringArray = dateString.split(' ');
|
const stringArray = dateString.split(' ');
|
||||||
const dateArray = stringArray[0].split('-');
|
const dateArray = stringArray[0].split('-');
|
||||||
|
@ -68,7 +66,9 @@ export function stringToDate(dateString: string): Date | null {
|
||||||
parseInt(dateArray[2], 10),
|
parseInt(dateArray[2], 10),
|
||||||
);
|
);
|
||||||
date.setHours(parseInt(timeArray[0], 10), parseInt(timeArray[1], 10), 0, 0);
|
date.setHours(parseInt(timeArray[0], 10), parseInt(timeArray[1], 10), 0, 0);
|
||||||
} else date = null;
|
} else {
|
||||||
|
date = null;
|
||||||
|
}
|
||||||
|
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,9 @@ export function getCurrentDateString(): string {
|
||||||
export function isEventBefore(event1Date: string, event2Date: string): boolean {
|
export function isEventBefore(event1Date: string, event2Date: string): boolean {
|
||||||
const date1 = stringToDate(event1Date);
|
const date1 = stringToDate(event1Date);
|
||||||
const date2 = stringToDate(event2Date);
|
const date2 = stringToDate(event2Date);
|
||||||
if (date1 !== null && date2 !== null) return date1 < date2;
|
if (date1 !== null && date2 !== null) {
|
||||||
|
return date1 < date2;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +125,9 @@ export function isEventBefore(event1Date: string, event2Date: string): boolean {
|
||||||
* @return {string|null} Date in format YYYY:MM:DD or null if given string is invalid
|
* @return {string|null} Date in format YYYY:MM:DD or null if given string is invalid
|
||||||
*/
|
*/
|
||||||
export function getDateOnlyString(dateString: string): string | null {
|
export function getDateOnlyString(dateString: string): string | null {
|
||||||
if (isEventDateStringFormatValid(dateString)) return dateString.split(' ')[0];
|
if (isEventDateStringFormatValid(dateString)) {
|
||||||
|
return dateString.split(' ')[0];
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +139,9 @@ export function getDateOnlyString(dateString: string): string | null {
|
||||||
* @return {string|null} Time in format HH:MM or null if given string is invalid
|
* @return {string|null} Time in format HH:MM or null if given string is invalid
|
||||||
*/
|
*/
|
||||||
export function getTimeOnlyString(dateString: string): string | null {
|
export function getTimeOnlyString(dateString: string): string | null {
|
||||||
if (isEventDateStringFormatValid(dateString)) return dateString.split(' ')[1];
|
if (isEventDateStringFormatValid(dateString)) {
|
||||||
|
return dateString.split(' ')[1];
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +154,7 @@ export function getTimeOnlyString(dateString: string): string | null {
|
||||||
* @param description The text to check
|
* @param description The text to check
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
export function isDescriptionEmpty(description: ?string): boolean {
|
export function isDescriptionEmpty(description?: string): boolean {
|
||||||
if (description !== undefined && description !== null) {
|
if (description !== undefined && description !== null) {
|
||||||
return (
|
return (
|
||||||
description
|
description
|
||||||
|
@ -177,10 +183,12 @@ export function generateEmptyCalendar(
|
||||||
): {[key: string]: Array<PlanningEventType>} {
|
): {[key: string]: Array<PlanningEventType>} {
|
||||||
const end = new Date(Date.now());
|
const end = new Date(Date.now());
|
||||||
end.setMonth(end.getMonth() + numberOfMonths);
|
end.setMonth(end.getMonth() + numberOfMonths);
|
||||||
const daysOfYear = {};
|
const daysOfYear: {[key: string]: Array<PlanningEventType>} = {};
|
||||||
for (let d = new Date(Date.now()); d <= end; d.setDate(d.getDate() + 1)) {
|
for (let d = new Date(Date.now()); d <= end; d.setDate(d.getDate() + 1)) {
|
||||||
const dateString = getDateOnlyString(dateToString(new Date(d), false));
|
const dateString = getDateOnlyString(dateToString(new Date(d), false));
|
||||||
if (dateString !== null) daysOfYear[dateString] = [];
|
if (dateString !== null) {
|
||||||
|
daysOfYear[dateString] = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return daysOfYear;
|
return daysOfYear;
|
||||||
}
|
}
|
||||||
|
@ -197,8 +205,9 @@ export function pushEventInOrder(
|
||||||
eventArray: Array<PlanningEventType>,
|
eventArray: Array<PlanningEventType>,
|
||||||
event: PlanningEventType,
|
event: PlanningEventType,
|
||||||
) {
|
) {
|
||||||
if (eventArray.length === 0) eventArray.push(event);
|
if (eventArray.length === 0) {
|
||||||
else {
|
eventArray.push(event);
|
||||||
|
} else {
|
||||||
for (let i = 0; i < eventArray.length; i += 1) {
|
for (let i = 0; i < eventArray.length; i += 1) {
|
||||||
if (isEventBefore(event.date_begin, eventArray[i].date_begin)) {
|
if (isEventBefore(event.date_begin, eventArray[i].date_begin)) {
|
||||||
eventArray.splice(i, 0, event);
|
eventArray.splice(i, 0, event);
|
||||||
|
@ -231,7 +240,9 @@ export function generateEventAgenda(
|
||||||
const dateString = getDateOnlyString(eventList[i].date_begin);
|
const dateString = getDateOnlyString(eventList[i].date_begin);
|
||||||
if (dateString != null) {
|
if (dateString != null) {
|
||||||
const eventArray = agendaItems[dateString];
|
const eventArray = agendaItems[dateString];
|
||||||
if (eventArray != null) pushEventInOrder(eventArray, eventList[i]);
|
if (eventArray != null) {
|
||||||
|
pushEventInOrder(eventArray, eventList[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return agendaItems;
|
return agendaItems;
|
|
@ -17,8 +17,6 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import type {ProxiwashMachineType} from '../screens/Proxiwash/ProxiwashScreen';
|
import type {ProxiwashMachineType} from '../screens/Proxiwash/ProxiwashScreen';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,16 +30,21 @@ import type {ProxiwashMachineType} from '../screens/Proxiwash/ProxiwashScreen';
|
||||||
*/
|
*/
|
||||||
export function getMachineEndDate(machine: ProxiwashMachineType): Date | null {
|
export function getMachineEndDate(machine: ProxiwashMachineType): Date | null {
|
||||||
const array = machine.endTime.split(':');
|
const array = machine.endTime.split(':');
|
||||||
let endDate = new Date(Date.now());
|
let endDate: Date | null = new Date(Date.now());
|
||||||
endDate.setHours(parseInt(array[0], 10), parseInt(array[1], 10));
|
endDate.setHours(parseInt(array[0], 10), parseInt(array[1], 10));
|
||||||
|
|
||||||
const limit = new Date(Date.now());
|
const limit = new Date(Date.now());
|
||||||
if (endDate < limit) {
|
if (endDate < limit) {
|
||||||
if (limit.getHours() > 12) {
|
if (limit.getHours() > 12) {
|
||||||
limit.setHours(limit.getHours() - 12);
|
limit.setHours(limit.getHours() - 12);
|
||||||
if (endDate < limit) endDate.setDate(endDate.getDate() + 1);
|
if (endDate < limit) {
|
||||||
else endDate = null;
|
endDate.setDate(endDate.getDate() + 1);
|
||||||
} else endDate = null;
|
} else {
|
||||||
|
endDate = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
endDate = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return endDate;
|
return endDate;
|
||||||
|
@ -63,8 +66,9 @@ export function isMachineWatched(
|
||||||
if (
|
if (
|
||||||
watchedMachine.number === machine.number &&
|
watchedMachine.number === machine.number &&
|
||||||
watchedMachine.endTime === machine.endTime
|
watchedMachine.endTime === machine.endTime
|
||||||
)
|
) {
|
||||||
watched = true;
|
watched = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return watched;
|
return watched;
|
||||||
}
|
}
|
||||||
|
@ -82,7 +86,9 @@ export function getMachineOfId(
|
||||||
): ProxiwashMachineType | null {
|
): ProxiwashMachineType | null {
|
||||||
let machineFound = null;
|
let machineFound = null;
|
||||||
allMachines.forEach((machine: ProxiwashMachineType) => {
|
allMachines.forEach((machine: ProxiwashMachineType) => {
|
||||||
if (machine.number === id) machineFound = machine;
|
if (machine.number === id) {
|
||||||
|
machineFound = machine;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return machineFound;
|
return machineFound;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +106,7 @@ export function getCleanedMachineWatched(
|
||||||
machineWatchedList: Array<ProxiwashMachineType>,
|
machineWatchedList: Array<ProxiwashMachineType>,
|
||||||
allMachines: Array<ProxiwashMachineType>,
|
allMachines: Array<ProxiwashMachineType>,
|
||||||
): Array<ProxiwashMachineType> {
|
): Array<ProxiwashMachineType> {
|
||||||
const newList = [];
|
const newList: Array<ProxiwashMachineType> = [];
|
||||||
machineWatchedList.forEach((watchedMachine: ProxiwashMachineType) => {
|
machineWatchedList.forEach((watchedMachine: ProxiwashMachineType) => {
|
||||||
const machine = getMachineOfId(watchedMachine.number, allMachines);
|
const machine = getMachineOfId(watchedMachine.number, allMachines);
|
||||||
if (
|
if (
|
|
@ -17,8 +17,6 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sanitizes the given string to improve search performance.
|
* Sanitizes the given string to improve search performance.
|
||||||
*
|
*
|
||||||
|
@ -60,7 +58,9 @@ export function isItemInCategoryFilter(
|
||||||
): boolean {
|
): boolean {
|
||||||
let itemFound = false;
|
let itemFound = false;
|
||||||
categories.forEach((cat: number | null) => {
|
categories.forEach((cat: number | null) => {
|
||||||
if (cat != null && filter.indexOf(cat) !== -1) itemFound = true;
|
if (cat != null && filter.indexOf(cat) !== -1) {
|
||||||
|
itemFound = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return itemFound;
|
return itemFound;
|
||||||
}
|
}
|
|
@ -17,10 +17,25 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
/**
|
||||||
|
* Gets the given services list without items of the given ids
|
||||||
import {Platform, StatusBar} from 'react-native';
|
*
|
||||||
import ThemeManager from '../managers/ThemeManager';
|
* @param idList The ids of items to remove
|
||||||
|
* @param sourceList The item list to use as source
|
||||||
|
* @returns {[]}
|
||||||
|
*/
|
||||||
|
export default function getStrippedServicesList<T extends {key: string}>(
|
||||||
|
idList: Array<string>,
|
||||||
|
sourceList: Array<T>,
|
||||||
|
) {
|
||||||
|
const newArray: Array<T> = [];
|
||||||
|
sourceList.forEach((item: T) => {
|
||||||
|
if (!idList.includes(item.key)) {
|
||||||
|
newArray.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return newArray;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a sublist of the given list with items of the given ids only
|
* Gets a sublist of the given list with items of the given ids only
|
||||||
|
@ -31,11 +46,11 @@ import ThemeManager from '../managers/ThemeManager';
|
||||||
* @param originalList The original list
|
* @param originalList The original list
|
||||||
* @returns {[]}
|
* @returns {[]}
|
||||||
*/
|
*/
|
||||||
export function getSublistWithIds<T>(
|
export function getSublistWithIds<T extends {key: string}>(
|
||||||
idList: Array<string>,
|
idList: Array<string>,
|
||||||
originalList: Array<{key: string, ...T}>,
|
originalList: Array<T>,
|
||||||
): Array<{key: string, ...T} | null> {
|
) {
|
||||||
const subList = [];
|
const subList: Array<T | null> = [];
|
||||||
for (let i = 0; i < idList.length; i += 1) {
|
for (let i = 0; i < idList.length; i += 1) {
|
||||||
subList.push(null);
|
subList.push(null);
|
||||||
}
|
}
|
||||||
|
@ -45,26 +60,10 @@ export function getSublistWithIds<T>(
|
||||||
if (idList.includes(item.key)) {
|
if (idList.includes(item.key)) {
|
||||||
subList[idList.indexOf(item.key)] = item;
|
subList[idList.indexOf(item.key)] = item;
|
||||||
itemsAdded += 1;
|
itemsAdded += 1;
|
||||||
if (itemsAdded === idList.length) break;
|
if (itemsAdded === idList.length) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return subList;
|
return subList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates status bar content color if on iOS only,
|
|
||||||
* as the android status bar is always set to black.
|
|
||||||
*/
|
|
||||||
export function setupStatusBar() {
|
|
||||||
if (ThemeManager.getNightMode()) {
|
|
||||||
StatusBar.setBarStyle('light-content', true);
|
|
||||||
} else {
|
|
||||||
StatusBar.setBarStyle('dark-content', true);
|
|
||||||
}
|
|
||||||
if (Platform.OS === 'android') {
|
|
||||||
StatusBar.setBackgroundColor(
|
|
||||||
ThemeManager.getCurrentTheme().colors.surface,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,20 +17,18 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import {Linking} from 'react-native';
|
import {Linking} from 'react-native';
|
||||||
|
|
||||||
export type ParsedUrlDataType = {
|
export type ParsedUrlDataType = {
|
||||||
route: string,
|
route: string;
|
||||||
data: {[key: string]: string},
|
data: {[key: string]: string};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ParsedUrlCallbackType = (parsedData: ParsedUrlDataType) => void;
|
export type ParsedUrlCallbackType = (parsedData: ParsedUrlDataType) => void;
|
||||||
|
|
||||||
type RawParsedUrlDataType = {
|
type RawParsedUrlDataType = {
|
||||||
path: string,
|
path: string;
|
||||||
queryParams: {[key: string]: string},
|
queryParams: {[key: string]: string};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,7 +67,7 @@ export default class URLHandler {
|
||||||
let parsedData: RawParsedUrlDataType | null = null;
|
let parsedData: RawParsedUrlDataType | null = null;
|
||||||
const urlNoScheme = url.replace(URLHandler.SCHEME, '');
|
const urlNoScheme = url.replace(URLHandler.SCHEME, '');
|
||||||
if (urlNoScheme != null) {
|
if (urlNoScheme != null) {
|
||||||
const params = {};
|
const params: {[key: string]: string} = {};
|
||||||
const [path, fullParamsString] = urlNoScheme.split('?');
|
const [path, fullParamsString] = urlNoScheme.split('?');
|
||||||
if (fullParamsString != null) {
|
if (fullParamsString != null) {
|
||||||
const paramsStringArray = fullParamsString.split('&');
|
const paramsStringArray = fullParamsString.split('&');
|
||||||
|
@ -80,7 +78,9 @@ export default class URLHandler {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (path != null) parsedData = {path, queryParams: params};
|
if (path != null) {
|
||||||
|
parsedData = {path, queryParams: params};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return parsedData;
|
return parsedData;
|
||||||
}
|
}
|
||||||
|
@ -99,11 +99,12 @@ export default class URLHandler {
|
||||||
if (rawParsedUrlData != null) {
|
if (rawParsedUrlData != null) {
|
||||||
const {path} = rawParsedUrlData;
|
const {path} = rawParsedUrlData;
|
||||||
const {queryParams} = rawParsedUrlData;
|
const {queryParams} = rawParsedUrlData;
|
||||||
if (URLHandler.isClubInformationLink(path))
|
if (URLHandler.isClubInformationLink(path)) {
|
||||||
parsedData = URLHandler.generateClubInformationData(queryParams);
|
parsedData = URLHandler.generateClubInformationData(queryParams);
|
||||||
else if (URLHandler.isPlanningInformationLink(path))
|
} else if (URLHandler.isPlanningInformationLink(path)) {
|
||||||
parsedData = URLHandler.generatePlanningInformationData(queryParams);
|
parsedData = URLHandler.generatePlanningInformationData(queryParams);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return parsedData;
|
return parsedData;
|
||||||
}
|
}
|
||||||
|
@ -145,16 +146,17 @@ export default class URLHandler {
|
||||||
* @returns {null|{route: string, data: {clubId: number}}}
|
* @returns {null|{route: string, data: {clubId: number}}}
|
||||||
*/
|
*/
|
||||||
static generateClubInformationData(params: {
|
static generateClubInformationData(params: {
|
||||||
[key: string]: string,
|
[key: string]: string;
|
||||||
}): ParsedUrlDataType | null {
|
}): ParsedUrlDataType | null {
|
||||||
if (params.id != null) {
|
if (params.id != null) {
|
||||||
const id = parseInt(params.id, 10);
|
const id = parseInt(params.id, 10);
|
||||||
if (!Number.isNaN(id))
|
if (!Number.isNaN(id)) {
|
||||||
return {
|
return {
|
||||||
route: URLHandler.CLUB_INFO_ROUTE,
|
route: URLHandler.CLUB_INFO_ROUTE,
|
||||||
data: {clubId: id.toString()},
|
data: {clubId: id.toString()},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +167,7 @@ export default class URLHandler {
|
||||||
* @returns {null|{route: string, data: {clubId: number}}}
|
* @returns {null|{route: string, data: {clubId: number}}}
|
||||||
*/
|
*/
|
||||||
static generatePlanningInformationData(params: {
|
static generatePlanningInformationData(params: {
|
||||||
[key: string]: string,
|
[key: string]: string;
|
||||||
}): ParsedUrlDataType | null {
|
}): ParsedUrlDataType | null {
|
||||||
if (params.id != null) {
|
if (params.id != null) {
|
||||||
const id = parseInt(params.id, 10);
|
const id = parseInt(params.id, 10);
|
||||||
|
@ -201,7 +203,9 @@ export default class URLHandler {
|
||||||
onUrl = ({url}: {url: string}) => {
|
onUrl = ({url}: {url: string}) => {
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
|
const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
|
||||||
if (data != null) this.onDetectURL(data);
|
if (data != null) {
|
||||||
|
this.onDetectURL(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -210,10 +214,12 @@ export default class URLHandler {
|
||||||
*
|
*
|
||||||
* @param url The url detected
|
* @param url The url detected
|
||||||
*/
|
*/
|
||||||
onInitialUrl = (url: ?string) => {
|
onInitialUrl = (url: string | null) => {
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
|
const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
|
||||||
if (data != null) this.onInitialURLParsed(data);
|
if (data != null) {
|
||||||
|
this.onInitialURLParsed(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -17,22 +17,23 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
import {Platform, StatusBar} from 'react-native';
|
||||||
|
import ThemeManager from '../managers/ThemeManager';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the given services list without items of the given ids
|
* Updates status bar content color if on iOS only,
|
||||||
*
|
* as the android status bar is always set to black.
|
||||||
* @param idList The ids of items to remove
|
|
||||||
* @param sourceList The item list to use as source
|
|
||||||
* @returns {[]}
|
|
||||||
*/
|
*/
|
||||||
export default function getStrippedServicesList<T>(
|
export function setupStatusBar() {
|
||||||
idList: Array<string>,
|
if (ThemeManager.getNightMode()) {
|
||||||
sourceList: Array<{key: string, ...T}>,
|
StatusBar.setBarStyle('light-content', true);
|
||||||
): Array<{key: string, ...T}> {
|
} else {
|
||||||
const newArray = [];
|
StatusBar.setBarStyle('dark-content', true);
|
||||||
sourceList.forEach((item: {key: string, ...T}) => {
|
}
|
||||||
if (!idList.includes(item.key)) newArray.push(item);
|
if (Platform.OS === 'android') {
|
||||||
});
|
StatusBar.setBackgroundColor(
|
||||||
return newArray;
|
ThemeManager.getCurrentTheme().colors.surface,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -17,8 +17,6 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
export const ERROR_TYPE = {
|
export const ERROR_TYPE = {
|
||||||
SUCCESS: 0,
|
SUCCESS: 0,
|
||||||
BAD_CREDENTIALS: 1,
|
BAD_CREDENTIALS: 1,
|
||||||
|
@ -34,15 +32,14 @@ export const ERROR_TYPE = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ApiDataLoginType = {
|
export type ApiDataLoginType = {
|
||||||
token: string,
|
token: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line flowtype/no-weak-types
|
|
||||||
export type ApiGenericDataType = {[key: string]: any};
|
export type ApiGenericDataType = {[key: string]: any};
|
||||||
|
|
||||||
type ApiResponseType = {
|
type ApiResponseType<T> = {
|
||||||
error: number,
|
error: number;
|
||||||
data: ApiGenericDataType,
|
data: T;
|
||||||
};
|
};
|
||||||
|
|
||||||
const API_ENDPOINT = 'https://www.amicale-insat.fr/api/';
|
const API_ENDPOINT = 'https://www.amicale-insat.fr/api/';
|
||||||
|
@ -55,11 +52,10 @@ const API_ENDPOINT = 'https://www.amicale-insat.fr/api/';
|
||||||
* @param response
|
* @param response
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
export function isApiResponseValid(response: ApiResponseType): boolean {
|
export function isApiResponseValid<T>(response: ApiResponseType<T>): boolean {
|
||||||
return (
|
return (
|
||||||
response != null &&
|
response != null &&
|
||||||
response.error != null &&
|
response.error != null &&
|
||||||
typeof response.error === 'number' &&
|
|
||||||
response.data != null &&
|
response.data != null &&
|
||||||
typeof response.data === 'object'
|
typeof response.data === 'object'
|
||||||
);
|
);
|
||||||
|
@ -76,18 +72,17 @@ export function isApiResponseValid(response: ApiResponseType): boolean {
|
||||||
* @param params The params to use for this request
|
* @param params The params to use for this request
|
||||||
* @returns {Promise<ApiGenericDataType>}
|
* @returns {Promise<ApiGenericDataType>}
|
||||||
*/
|
*/
|
||||||
export async function apiRequest(
|
export async function apiRequest<T>(
|
||||||
path: string,
|
path: string,
|
||||||
method: string,
|
method: string,
|
||||||
params?: {...},
|
params?: object,
|
||||||
): Promise<ApiGenericDataType> {
|
): Promise<T> {
|
||||||
return new Promise(
|
return new Promise(
|
||||||
(
|
(resolve: (data: T) => void, reject: (error: number) => void) => {
|
||||||
resolve: (data: ApiGenericDataType) => void,
|
|
||||||
reject: (error: number) => void,
|
|
||||||
) => {
|
|
||||||
let requestParams = {};
|
let requestParams = {};
|
||||||
if (params != null) requestParams = {...params};
|
if (params != null) {
|
||||||
|
requestParams = {...params};
|
||||||
|
}
|
||||||
fetch(API_ENDPOINT + path, {
|
fetch(API_ENDPOINT + path, {
|
||||||
method,
|
method,
|
||||||
headers: new Headers({
|
headers: new Headers({
|
||||||
|
@ -96,14 +91,20 @@ export async function apiRequest(
|
||||||
}),
|
}),
|
||||||
body: JSON.stringify(requestParams),
|
body: JSON.stringify(requestParams),
|
||||||
})
|
})
|
||||||
.then(async (response: Response): Promise<ApiResponseType> =>
|
.then(
|
||||||
|
async (response: Response): Promise<ApiResponseType<T>> =>
|
||||||
response.json(),
|
response.json(),
|
||||||
)
|
)
|
||||||
.then((response: ApiResponseType) => {
|
.then((response: ApiResponseType<T>) => {
|
||||||
if (isApiResponseValid(response)) {
|
if (isApiResponseValid(response)) {
|
||||||
if (response.error === ERROR_TYPE.SUCCESS) resolve(response.data);
|
if (response.error === ERROR_TYPE.SUCCESS) {
|
||||||
else reject(response.error);
|
resolve(response.data);
|
||||||
} else reject(ERROR_TYPE.SERVER_ERROR);
|
} else {
|
||||||
|
reject(response.error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reject(ERROR_TYPE.SERVER_ERROR);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((): void => reject(ERROR_TYPE.CONNECTION_ERROR));
|
.catch((): void => reject(ERROR_TYPE.CONNECTION_ERROR));
|
||||||
},
|
},
|
||||||
|
@ -121,14 +122,10 @@ export async function apiRequest(
|
||||||
* @param url The urls to fetch data from
|
* @param url The urls to fetch data from
|
||||||
* @return Promise<any>
|
* @return Promise<any>
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line flowtype/no-weak-types
|
|
||||||
export async function readData(url: string): Promise<any> {
|
export async function readData(url: string): Promise<any> {
|
||||||
// eslint-disable-next-line flowtype/no-weak-types
|
|
||||||
return new Promise((resolve: (response: any) => void, reject: () => void) => {
|
return new Promise((resolve: (response: any) => void, reject: () => void) => {
|
||||||
fetch(url)
|
fetch(url)
|
||||||
// eslint-disable-next-line flowtype/no-weak-types
|
|
||||||
.then(async (response: Response): Promise<any> => response.json())
|
.then(async (response: Response): Promise<any> => response.json())
|
||||||
// eslint-disable-next-line flowtype/no-weak-types
|
|
||||||
.then((data: any): void => resolve(data))
|
.then((data: any): void => resolve(data))
|
||||||
.catch((): void => reject());
|
.catch((): void => reject());
|
||||||
});
|
});
|
|
@ -17,8 +17,6 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {useCollapsibleStack} from 'react-navigation-collapsible';
|
import {useCollapsibleStack} from 'react-navigation-collapsible';
|
||||||
|
|
||||||
|
@ -35,18 +33,12 @@ import {useCollapsibleStack} from 'react-navigation-collapsible';
|
||||||
* @param Component The component to use Collapsible with
|
* @param Component The component to use Collapsible with
|
||||||
* @returns {React.ComponentType<any>}
|
* @returns {React.ComponentType<any>}
|
||||||
*/
|
*/
|
||||||
export default function withCollapsible(
|
export default function withCollapsible(Component: React.ComponentType<any>) {
|
||||||
// eslint-disable-next-line flowtype/no-weak-types
|
return React.forwardRef((props: any, ref: any) => {
|
||||||
Component: React.ComponentType<any>,
|
|
||||||
// eslint-disable-next-line flowtype/no-weak-types
|
|
||||||
): React$AbstractComponent<any, any> {
|
|
||||||
// eslint-disable-next-line flowtype/no-weak-types
|
|
||||||
return React.forwardRef((props: any, ref: any): React.Node => {
|
|
||||||
return (
|
return (
|
||||||
<Component
|
<Component
|
||||||
collapsibleStack={useCollapsibleStack()}
|
collapsibleStack={useCollapsibleStack()}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
Loading…
Reference in a new issue