diff --git a/package-lock.json b/package-lock.json
index 6a2db43..b88f93a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2501,6 +2501,12 @@
"resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.36.tgz",
"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": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
@@ -2602,6 +2608,16 @@
"@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": {
"version": "16.9.3",
"resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-16.9.3.tgz",
diff --git a/package.json b/package.json
index 1248aab..f46612a 100644
--- a/package.json
+++ b/package.json
@@ -66,6 +66,8 @@
"@babel/core": "^7.11.0",
"@babel/runtime": "^7.11.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/react-native": "^0.63.2",
"@types/react-test-renderer": "^16.9.2",
diff --git a/src/managers/AprilFoolsManager.js b/src/managers/AprilFoolsManager.ts
similarity index 95%
rename from src/managers/AprilFoolsManager.js
rename to src/managers/AprilFoolsManager.ts
index 600bad8..d609db0 100644
--- a/src/managers/AprilFoolsManager.js
+++ b/src/managers/AprilFoolsManager.ts
@@ -17,10 +17,7 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
import type {ProxiwashMachineType} from '../screens/Proxiwash/ProxiwashScreen';
-import type {CustomThemeType} from './ThemeManager';
import type {RuFoodCategoryType} from '../screens/Services/SelfMenuScreen';
/**
@@ -57,8 +54,9 @@ export default class AprilFoolsManager {
* @returns {ThemeManager}
*/
static getInstance(): AprilFoolsManager {
- if (AprilFoolsManager.instance == null)
+ if (AprilFoolsManager.instance == null) {
AprilFoolsManager.instance = new AprilFoolsManager();
+ }
return AprilFoolsManager.instance;
}
@@ -130,7 +128,9 @@ export default class AprilFoolsManager {
* @param currentTheme
* @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 {
...currentTheme,
colors: {
diff --git a/src/managers/AsyncStorageManager.ts b/src/managers/AsyncStorageManager.ts
index 483d0c8..f125936 100644
--- a/src/managers/AsyncStorageManager.ts
+++ b/src/managers/AsyncStorageManager.ts
@@ -198,7 +198,7 @@ export default class AsyncStorageManager {
* @param key
* @returns {{...}}
*/
- static getObject(key: string): object | Array {
+ static getObject(key: string): T {
return JSON.parse(AsyncStorageManager.getString(key));
}
diff --git a/src/managers/ConnectionManager.js b/src/managers/ConnectionManager.ts
similarity index 80%
rename from src/managers/ConnectionManager.js
rename to src/managers/ConnectionManager.ts
index 781b31e..51c160f 100644
--- a/src/managers/ConnectionManager.js
+++ b/src/managers/ConnectionManager.ts
@@ -20,7 +20,7 @@
// @flow
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';
/**
@@ -40,12 +40,10 @@ const AUTH_PATH = 'password';
export default class ConnectionManager {
static instance: ConnectionManager | null = null;
- #email: string;
-
- #token: string | null;
+ private token: string | null;
constructor() {
- this.#token = null;
+ this.token = null;
}
/**
@@ -54,8 +52,9 @@ export default class ConnectionManager {
* @returns {ConnectionManager}
*/
static getInstance(): ConnectionManager {
- if (ConnectionManager.instance == null)
+ if (ConnectionManager.instance == null) {
ConnectionManager.instance = new ConnectionManager();
+ }
return ConnectionManager.instance;
}
@@ -65,7 +64,7 @@ export default class ConnectionManager {
* @returns {string | null}
*/
getToken(): string | null {
- return this.#token;
+ return this.token;
}
/**
@@ -77,18 +76,17 @@ export default class ConnectionManager {
return new Promise(
(resolve: (token: string) => void, reject: () => void) => {
const token = this.getToken();
- if (token != null) resolve(token);
- else {
+ if (token != null) {
+ resolve(token);
+ } else {
Keychain.getInternetCredentials(SERVER_NAME)
.then((data: Keychain.UserCredentials | false) => {
- if (
- data != null &&
- data.password != null &&
- typeof data.password === 'string'
- ) {
- this.#token = data.password;
- resolve(this.#token);
- } else reject();
+ if (data && data.password != null) {
+ this.token = data.password;
+ resolve(this.token);
+ } else {
+ reject();
+ }
})
.catch((): void => reject());
}
@@ -116,8 +114,7 @@ export default class ConnectionManager {
return new Promise((resolve: () => void, reject: () => void) => {
Keychain.setInternetCredentials(SERVER_NAME, 'token', token)
.then(() => {
- this.#token = token;
- this.#email = email;
+ this.token = token;
resolve();
})
.catch((): void => reject());
@@ -133,7 +130,7 @@ export default class ConnectionManager {
return new Promise((resolve: () => void, reject: () => void) => {
Keychain.resetInternetCredentials(SERVER_NAME)
.then(() => {
- this.#token = null;
+ this.token = null;
resolve();
})
.catch((): void => reject());
@@ -156,13 +153,15 @@ export default class ConnectionManager {
email,
password,
};
- apiRequest(AUTH_PATH, 'POST', data)
+ apiRequest(AUTH_PATH, 'POST', data)
.then((response: ApiDataLoginType) => {
if (response.token != null) {
this.saveLogin(email, response.token)
.then((): void => resolve())
.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));
},
@@ -176,24 +175,23 @@ export default class ConnectionManager {
* @param params
* @returns Promise
*/
- async authenticatedRequest(
+ async authenticatedRequest(
path: string,
- params: {...},
- ): Promise {
+ params: {[key: string]: any},
+ ): Promise {
return new Promise(
- (
- resolve: (response: ApiGenericDataType) => void,
- reject: (error: number) => void,
- ) => {
+ (resolve: (response: T) => void, reject: (error: number) => void) => {
if (this.getToken() !== null) {
const data = {
...params,
token: this.getToken(),
};
- apiRequest(path, 'POST', data)
- .then((response: ApiGenericDataType): void => resolve(response))
+ apiRequest(path, 'POST', data)
+ .then((response: T): void => resolve(response))
.catch((error: number): void => reject(error));
- } else reject(ERROR_TYPE.TOKEN_RETRIEVE);
+ } else {
+ reject(ERROR_TYPE.TOKEN_RETRIEVE);
+ }
},
);
}
diff --git a/src/managers/DashboardManager.js b/src/managers/DashboardManager.ts
similarity index 91%
rename from src/managers/DashboardManager.js
rename to src/managers/DashboardManager.ts
index a813d56..12035a6 100644
--- a/src/managers/DashboardManager.js
+++ b/src/managers/DashboardManager.ts
@@ -21,12 +21,12 @@
import type {ServiceItemType} from './ServicesManager';
import ServicesManager from './ServicesManager';
-import {getSublistWithIds} from '../utils/Utils';
+import {getSublistWithIds} from '../utils/Services';
import AsyncStorageManager from './AsyncStorageManager';
export default class DashboardManager extends ServicesManager {
getCurrentDashboard(): Array {
- const dashboardIdList = AsyncStorageManager.getObject(
+ const dashboardIdList = AsyncStorageManager.getObject>(
AsyncStorageManager.PREFERENCES.dashboardItems.key,
);
const allDatasets = [
diff --git a/src/managers/DateManager.js b/src/managers/DateManager.ts
similarity index 95%
rename from src/managers/DateManager.js
rename to src/managers/DateManager.ts
index ec2ebd0..f699e68 100644
--- a/src/managers/DateManager.js
+++ b/src/managers/DateManager.ts
@@ -17,8 +17,6 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
import i18n from 'i18n-js';
/**
@@ -28,9 +26,9 @@ import i18n from 'i18n-js';
export default class DateManager {
static instance: DateManager | null = null;
- daysOfWeek = [];
+ daysOfWeek: Array = [];
- monthsOfYear = [];
+ monthsOfYear: Array = [];
constructor() {
this.daysOfWeek.push(i18n.t('date.daysOfWeek.sunday')); // 0 represents sunday
@@ -60,7 +58,9 @@ export default class DateManager {
* @returns {DateManager}
*/
static getInstance(): DateManager {
- if (DateManager.instance == null) DateManager.instance = new DateManager();
+ if (DateManager.instance == null) {
+ DateManager.instance = new DateManager();
+ }
return DateManager.instance;
}
diff --git a/src/managers/ServicesManager.js b/src/managers/ServicesManager.ts
similarity index 94%
rename from src/managers/ServicesManager.js
rename to src/managers/ServicesManager.ts
index d3ee8f0..b33237d 100644
--- a/src/managers/ServicesManager.js
+++ b/src/managers/ServicesManager.ts
@@ -17,8 +17,6 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
import i18n from 'i18n-js';
import {StackNavigationProp} from '@react-navigation/stack';
import AvailableWebsites from '../constants/AvailableWebsites';
@@ -93,24 +91,24 @@ export const SERVICES_CATEGORIES_KEY = {
};
export type ServiceItemType = {
- key: string,
- title: string,
- subtitle: string,
- image: string,
- onPress: () => void,
- badgeFunction?: (dashboard: FullDashboardType) => number,
+ key: string;
+ title: string;
+ subtitle: string;
+ image: string;
+ onPress: () => void;
+ badgeFunction?: (dashboard: FullDashboardType) => number;
};
export type ServiceCategoryType = {
- key: string,
- title: string,
- subtitle: string,
- image: string | number,
- content: Array,
+ key: string;
+ title: string;
+ subtitle: string;
+ image: string | number;
+ content: Array;
};
export default class ServicesManager {
- navigation: StackNavigationProp;
+ navigation: StackNavigationProp;
amicaleDataset: Array;
@@ -122,7 +120,7 @@ export default class ServicesManager {
categoriesDataset: Array;
- constructor(nav: StackNavigationProp) {
+ constructor(nav: StackNavigationProp) {
this.navigation = nav;
this.amicaleDataset = [
{
@@ -336,9 +334,11 @@ export default class ServicesManager {
* @returns {null}
*/
onAmicaleServicePress(route: string) {
- if (ConnectionManager.getInstance().isLoggedIn())
+ if (ConnectionManager.getInstance().isLoggedIn()) {
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}
*/
getAmicaleServices(excludedItems?: Array): Array {
- if (excludedItems != null)
+ if (excludedItems != null) {
return getStrippedServicesList(excludedItems, this.amicaleDataset);
+ }
return this.amicaleDataset;
}
@@ -360,8 +361,9 @@ export default class ServicesManager {
* @returns {Array}
*/
getStudentServices(excludedItems?: Array): Array {
- if (excludedItems != null)
+ if (excludedItems != null) {
return getStrippedServicesList(excludedItems, this.studentsDataset);
+ }
return this.studentsDataset;
}
@@ -372,8 +374,9 @@ export default class ServicesManager {
* @returns {Array}
*/
getINSAServices(excludedItems?: Array): Array {
- if (excludedItems != null)
+ if (excludedItems != null) {
return getStrippedServicesList(excludedItems, this.insaDataset);
+ }
return this.insaDataset;
}
@@ -384,8 +387,9 @@ export default class ServicesManager {
* @returns {Array}
*/
getSpecialServices(excludedItems?: Array): Array {
- if (excludedItems != null)
+ if (excludedItems != null) {
return getStrippedServicesList(excludedItems, this.specialDataset);
+ }
return this.specialDataset;
}
@@ -396,8 +400,9 @@ export default class ServicesManager {
* @returns {Array}
*/
getCategories(excludedItems?: Array): Array {
- if (excludedItems != null)
+ if (excludedItems != null) {
return getStrippedServicesList(excludedItems, this.categoriesDataset);
+ }
return this.categoriesDataset;
}
}
diff --git a/src/utils/AutoHideHandler.js b/src/utils/AutoHideHandler.ts
similarity index 89%
rename from src/utils/AutoHideHandler.js
rename to src/utils/AutoHideHandler.ts
index 69d7eb8..c3e7662 100644
--- a/src/utils/AutoHideHandler.js
+++ b/src/utils/AutoHideHandler.ts
@@ -17,22 +17,12 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
+import {NativeScrollEvent, NativeSyntheticEvent} from 'react-native';
const speedOffset = 5;
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
*/
@@ -46,6 +36,7 @@ export default class AutoHideHandler {
constructor(startHidden: boolean) {
this.listeners = [];
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
*/
- onScroll(event: OnScrollType) {
+ onScroll(event: NativeSyntheticEvent) {
const {nativeEvent} = event;
const speed =
nativeEvent.contentOffset.y < 0
diff --git a/src/utils/CollapsibleUtils.js b/src/utils/CollapsibleUtils.tsx
similarity index 79%
rename from src/utils/CollapsibleUtils.js
rename to src/utils/CollapsibleUtils.tsx
index 0f9f6aa..921cb12 100644
--- a/src/utils/CollapsibleUtils.js
+++ b/src/utils/CollapsibleUtils.tsx
@@ -17,12 +17,20 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
import * as React from 'react';
import {useTheme} from 'react-native-paper';
import {createCollapsibleStack} from 'react-navigation-collapsible';
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,
+ StackNavigationState,
+ StackNavigationOptions,
+ StackNavigationEventMap,
+ typeof StackNavigator
+>;
/**
* 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
* @returns {JSX.Element}
*/
-export function createScreenCollapsibleStack(
+export function CreateScreenCollapsibleStack(
name: string,
- Stack: StackNavigator,
- // eslint-disable-next-line flowtype/no-weak-types
+ Stack: StackNavigatorType,
component: React.ComponentType,
title: string,
- useNativeDriver?: boolean,
- options?: StackNavigationOptions,
+ useNativeDriver: boolean = true,
+ options: StackNavigationOptions = {},
headerColor?: string,
-): React.Node {
+) {
const {colors} = useTheme();
- const screenOptions = options != null ? options : {};
return createCollapsibleStack(
,
{
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(
name: string,
- Stack: StackNavigator,
- // eslint-disable-next-line flowtype/no-weak-types
+ Stack: StackNavigatorType,
component: React.ComponentType,
title: string,
-): React.Node {
- return createScreenCollapsibleStack(name, Stack, component, title, false);
+) {
+ return CreateScreenCollapsibleStack(name, Stack, component, title, false);
}
diff --git a/src/utils/EquipmentBooking.js b/src/utils/EquipmentBooking.ts
similarity index 86%
rename from src/utils/EquipmentBooking.js
rename to src/utils/EquipmentBooking.ts
index 05b96cf..e5e1d0f 100644
--- a/src/utils/EquipmentBooking.js
+++ b/src/utils/EquipmentBooking.ts
@@ -17,12 +17,9 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
import i18n from 'i18n-js';
import type {DeviceType} from '../screens/Amicale/Equipment/EquipmentListScreen';
import DateManager from '../managers/DateManager';
-import type {CustomThemeType} from '../managers/ThemeManager';
import type {MarkedDatesObjectType} from '../screens/Amicale/Equipment/EquipmentRentScreen';
/**
@@ -56,10 +53,12 @@ export function isEquipmentAvailable(item: DeviceType): boolean {
let isAvailable = true;
const today = getCurrentDay();
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 end = new Date(date.end);
- if (!(today < start || today > end)) isAvailable = false;
+ if (!(today < start || today > end)) {
+ isAvailable = false;
+ }
});
return isAvailable;
}
@@ -73,11 +72,13 @@ export function isEquipmentAvailable(item: DeviceType): boolean {
export function getFirstEquipmentAvailability(item: DeviceType): Date {
let firstAvailability = getCurrentDay();
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 end = new Date(date.end);
end.setDate(end.getDate() + 1);
- if (firstAvailability >= start) firstAvailability = end;
+ if (firstAvailability >= start) {
+ firstAvailability = end;
+ }
});
return firstAvailability;
}
@@ -93,23 +94,24 @@ export function getRelativeDateString(date: Date): string {
const monthDelta = date.getUTCMonth() - today.getUTCMonth();
const dayDelta = date.getUTCDate() - today.getUTCDate();
let translatedString = i18n.t('screens.equipment.today');
- if (yearDelta > 0)
+ if (yearDelta > 0) {
translatedString = i18n.t('screens.equipment.otherYear', {
date: date.getDate(),
month: DateManager.getInstance().getMonthsOfYear()[date.getMonth()],
year: date.getFullYear(),
});
- else if (monthDelta > 0)
+ } else if (monthDelta > 0) {
translatedString = i18n.t('screens.equipment.otherMonth', {
date: date.getDate(),
month: DateManager.getInstance().getMonthsOfYear()[date.getMonth()],
});
- else if (dayDelta > 1)
+ } else if (dayDelta > 1) {
translatedString = i18n.t('screens.equipment.thisMonth', {
date: date.getDate(),
});
- else if (dayDelta === 1)
+ } else if (dayDelta === 1) {
translatedString = i18n.t('screens.equipment.tomorrow');
+ }
return translatedString;
}
@@ -162,8 +164,11 @@ export function getValidRange(
(direction === 1 && date < limit) ||
(direction === -1 && date > limit)
) {
- if (direction === 1) validRange.push(getISODate(date));
- else validRange.unshift(getISODate(date));
+ if (direction === 1) {
+ validRange.push(getISODate(date));
+ } else {
+ validRange.unshift(getISODate(date));
+ }
date.setDate(date.getDate() + direction);
}
return validRange;
@@ -180,17 +185,27 @@ export function getValidRange(
*/
export function generateMarkedDates(
isSelection: boolean,
- theme: CustomThemeType,
+ theme: ReactNativePaper.Theme,
range: Array,
): MarkedDatesObjectType {
- const markedDates = {};
+ const markedDates: {
+ [key: string]: {
+ startingDay: boolean;
+ endingDay: boolean;
+ color: string;
+ };
+ } = {};
for (let i = 0; i < range.length; i += 1) {
const isStart = i === 0;
const isEnd = i === range.length - 1;
let color;
- if (isSelection && (isStart || isEnd)) color = theme.colors.primary;
- else if (isSelection) color = theme.colors.danger;
- else color = theme.colors.textDisabled;
+ if (isSelection && (isStart || isEnd)) {
+ color = theme.colors.primary;
+ } else if (isSelection) {
+ color = theme.colors.danger;
+ } else {
+ color = theme.colors.textDisabled;
+ }
markedDates[range[i]] = {
startingDay: isStart,
endingDay: isEnd,
diff --git a/src/utils/Home.js b/src/utils/Home.ts
similarity index 81%
rename from src/utils/Home.js
rename to src/utils/Home.ts
index 7b9764d..efebafd 100644
--- a/src/utils/Home.js
+++ b/src/utils/Home.ts
@@ -17,8 +17,6 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
import {stringToDate} from './Planning';
import type {PlanningEventType} from './Planning';
@@ -29,13 +27,15 @@ import type {PlanningEventType} from './Planning';
*/
export function getTodayEventTimeLimit(): Date {
const now = new Date();
- if (now.getDay() === 4)
+ if (now.getDay() === 4) {
// Thursday
now.setHours(11, 30, 0);
- else if (now.getDay() === 6 || now.getDay() === 0)
+ } else if (now.getDay() === 6 || now.getDay() === 0) {
// Weekend
now.setHours(0, 0, 0);
- else now.setHours(17, 30, 0);
+ } else {
+ now.setHours(17, 30, 0);
+ }
return now;
}
@@ -50,7 +50,7 @@ export function getEventsAfterLimit(
events: Array,
limit: Date,
): Array {
- const validEvents = [];
+ const validEvents: Array = [];
events.forEach((event: PlanningEventType) => {
const startDate = stringToDate(event.date_begin);
if (startDate != null && startDate >= limit) {
@@ -68,11 +68,13 @@ export function getEventsAfterLimit(
export function getFutureEvents(
events: Array,
): Array {
- const validEvents = [];
+ const validEvents: Array = [];
const now = new Date();
events.forEach((event: PlanningEventType) => {
const startDate = stringToDate(event.date_begin);
- if (startDate != null && startDate > now) validEvents.push(event);
+ if (startDate != null && startDate > now) {
+ validEvents.push(event);
+ }
});
return validEvents;
}
@@ -92,8 +94,13 @@ export function getDisplayEvent(
events,
getTodayEventTimeLimit(),
);
- if (eventsAfterLimit.length > 0) [displayEvent] = eventsAfterLimit;
- else [displayEvent] = events;
- } else if (events.length === 1) [displayEvent] = events;
+ if (eventsAfterLimit.length > 0) {
+ [displayEvent] = eventsAfterLimit;
+ } else {
+ [displayEvent] = events;
+ }
+ } else if (events.length === 1) {
+ [displayEvent] = events;
+ }
return displayEvent;
}
diff --git a/src/utils/Locales.js b/src/utils/Locales.ts
similarity index 87%
rename from src/utils/Locales.js
rename to src/utils/Locales.ts
index b44df46..3f6f144 100644
--- a/src/utils/Locales.js
+++ b/src/utils/Locales.ts
@@ -17,8 +17,6 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
import i18n from 'i18n-js';
import * as RNLocalize from 'react-native-localize';
@@ -28,9 +26,7 @@ import fr from '../../locales/fr.json';
const initLocales = () => {
i18n.fallbacks = true;
i18n.translations = {fr, en};
- i18n.locale = RNLocalize.findBestAvailableLanguage([
- 'en',
- 'fr',
- ]).languageTag;
-}
+ const bestLanguage = RNLocalize.findBestAvailableLanguage(['en', 'fr']);
+ i18n.locale = bestLanguage ? bestLanguage.languageTag : 'en';
+};
export default initLocales;
diff --git a/src/utils/Notifications.js b/src/utils/Notifications.ts
similarity index 92%
rename from src/utils/Notifications.js
rename to src/utils/Notifications.ts
index 7fc279c..1bb8acd 100644
--- a/src/utils/Notifications.js
+++ b/src/utils/Notifications.ts
@@ -17,8 +17,6 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
import {
checkNotifications,
requestNotifications,
@@ -41,12 +39,17 @@ const reminderIdFactor = 100;
export async function askPermissions(): Promise {
return new Promise((resolve: () => void, reject: () => void) => {
checkNotifications().then(({status}: {status: string}) => {
- if (status === RESULTS.GRANTED) resolve();
- else if (status === RESULTS.BLOCKED) reject();
- else {
- requestNotifications().then((result: {status: string}) => {
- if (result.status === RESULTS.GRANTED) resolve();
- else reject();
+ if (status === RESULTS.GRANTED) {
+ resolve();
+ } else if (status === RESULTS.BLOCKED) {
+ reject();
+ } else {
+ requestNotifications([]).then((result: {status: string}) => {
+ if (result.status === RESULTS.GRANTED) {
+ resolve();
+ } else {
+ reject();
+ }
});
}
});
diff --git a/src/utils/Planning.js b/src/utils/Planning.ts
similarity index 87%
rename from src/utils/Planning.js
rename to src/utils/Planning.ts
index aa54be0..81a19f7 100644
--- a/src/utils/Planning.js
+++ b/src/utils/Planning.ts
@@ -17,18 +17,16 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
export type PlanningEventType = {
- id: number,
- title: string,
- date_begin: string,
- club: string,
- category_id: number,
- description: string,
- place: string,
- url: string,
- logo: string | null,
+ id: number;
+ title: string;
+ date_begin: string;
+ club: string;
+ category_id: number;
+ description: string;
+ place: string;
+ url: string;
+ logo: string | null;
};
// 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
* @return {boolean}
*/
-export function isEventDateStringFormatValid(dateString: ?string): boolean {
+export function isEventDateStringFormatValid(dateString?: string): boolean {
return (
dateString !== undefined &&
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
*/
export function stringToDate(dateString: string): Date | null {
- let date = new Date();
+ let date: Date | null = new Date();
if (isEventDateStringFormatValid(dateString)) {
const stringArray = dateString.split(' ');
const dateArray = stringArray[0].split('-');
@@ -68,7 +66,9 @@ export function stringToDate(dateString: string): Date | null {
parseInt(dateArray[2], 10),
);
date.setHours(parseInt(timeArray[0], 10), parseInt(timeArray[1], 10), 0, 0);
- } else date = null;
+ } else {
+ date = null;
+ }
return date;
}
@@ -111,7 +111,9 @@ export function getCurrentDateString(): string {
export function isEventBefore(event1Date: string, event2Date: string): boolean {
const date1 = stringToDate(event1Date);
const date2 = stringToDate(event2Date);
- if (date1 !== null && date2 !== null) return date1 < date2;
+ if (date1 !== null && date2 !== null) {
+ return date1 < date2;
+ }
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
*/
export function getDateOnlyString(dateString: string): string | null {
- if (isEventDateStringFormatValid(dateString)) return dateString.split(' ')[0];
+ if (isEventDateStringFormatValid(dateString)) {
+ return dateString.split(' ')[0];
+ }
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
*/
export function getTimeOnlyString(dateString: string): string | null {
- if (isEventDateStringFormatValid(dateString)) return dateString.split(' ')[1];
+ if (isEventDateStringFormatValid(dateString)) {
+ return dateString.split(' ')[1];
+ }
return null;
}
@@ -148,7 +154,7 @@ export function getTimeOnlyString(dateString: string): string | null {
* @param description The text to check
* @return {boolean}
*/
-export function isDescriptionEmpty(description: ?string): boolean {
+export function isDescriptionEmpty(description?: string): boolean {
if (description !== undefined && description !== null) {
return (
description
@@ -177,10 +183,12 @@ export function generateEmptyCalendar(
): {[key: string]: Array} {
const end = new Date(Date.now());
end.setMonth(end.getMonth() + numberOfMonths);
- const daysOfYear = {};
+ const daysOfYear: {[key: string]: Array} = {};
for (let d = new Date(Date.now()); d <= end; d.setDate(d.getDate() + 1)) {
const dateString = getDateOnlyString(dateToString(new Date(d), false));
- if (dateString !== null) daysOfYear[dateString] = [];
+ if (dateString !== null) {
+ daysOfYear[dateString] = [];
+ }
}
return daysOfYear;
}
@@ -197,8 +205,9 @@ export function pushEventInOrder(
eventArray: Array,
event: PlanningEventType,
) {
- if (eventArray.length === 0) eventArray.push(event);
- else {
+ if (eventArray.length === 0) {
+ eventArray.push(event);
+ } else {
for (let i = 0; i < eventArray.length; i += 1) {
if (isEventBefore(event.date_begin, eventArray[i].date_begin)) {
eventArray.splice(i, 0, event);
@@ -231,7 +240,9 @@ export function generateEventAgenda(
const dateString = getDateOnlyString(eventList[i].date_begin);
if (dateString != null) {
const eventArray = agendaItems[dateString];
- if (eventArray != null) pushEventInOrder(eventArray, eventList[i]);
+ if (eventArray != null) {
+ pushEventInOrder(eventArray, eventList[i]);
+ }
}
}
return agendaItems;
diff --git a/src/utils/Proxiwash.js b/src/utils/Proxiwash.ts
similarity index 90%
rename from src/utils/Proxiwash.js
rename to src/utils/Proxiwash.ts
index d3d204a..e2e202b 100644
--- a/src/utils/Proxiwash.js
+++ b/src/utils/Proxiwash.ts
@@ -17,8 +17,6 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
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 {
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));
const limit = new Date(Date.now());
if (endDate < limit) {
if (limit.getHours() > 12) {
limit.setHours(limit.getHours() - 12);
- if (endDate < limit) endDate.setDate(endDate.getDate() + 1);
- else endDate = null;
- } else endDate = null;
+ if (endDate < limit) {
+ endDate.setDate(endDate.getDate() + 1);
+ } else {
+ endDate = null;
+ }
+ } else {
+ endDate = null;
+ }
}
return endDate;
@@ -63,8 +66,9 @@ export function isMachineWatched(
if (
watchedMachine.number === machine.number &&
watchedMachine.endTime === machine.endTime
- )
+ ) {
watched = true;
+ }
});
return watched;
}
@@ -82,7 +86,9 @@ export function getMachineOfId(
): ProxiwashMachineType | null {
let machineFound = null;
allMachines.forEach((machine: ProxiwashMachineType) => {
- if (machine.number === id) machineFound = machine;
+ if (machine.number === id) {
+ machineFound = machine;
+ }
});
return machineFound;
}
@@ -100,7 +106,7 @@ export function getCleanedMachineWatched(
machineWatchedList: Array,
allMachines: Array,
): Array {
- const newList = [];
+ const newList: Array = [];
machineWatchedList.forEach((watchedMachine: ProxiwashMachineType) => {
const machine = getMachineOfId(watchedMachine.number, allMachines);
if (
diff --git a/src/utils/Search.js b/src/utils/Search.ts
similarity index 95%
rename from src/utils/Search.js
rename to src/utils/Search.ts
index addfa0f..2b2c67f 100644
--- a/src/utils/Search.js
+++ b/src/utils/Search.ts
@@ -17,8 +17,6 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
/**
* Sanitizes the given string to improve search performance.
*
@@ -60,7 +58,9 @@ export function isItemInCategoryFilter(
): boolean {
let itemFound = false;
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;
}
diff --git a/src/utils/Utils.js b/src/utils/Services.ts
similarity index 64%
rename from src/utils/Utils.js
rename to src/utils/Services.ts
index bf35582..9d82611 100644
--- a/src/utils/Utils.js
+++ b/src/utils/Services.ts
@@ -17,10 +17,25 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
-import {Platform, StatusBar} from 'react-native';
-import ThemeManager from '../managers/ThemeManager';
+/**
+ * Gets the given services list without items of the given ids
+ *
+ * @param idList The ids of items to remove
+ * @param sourceList The item list to use as source
+ * @returns {[]}
+ */
+export default function getStrippedServicesList(
+ idList: Array,
+ sourceList: Array,
+) {
+ const newArray: Array = [];
+ 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
@@ -31,11 +46,11 @@ import ThemeManager from '../managers/ThemeManager';
* @param originalList The original list
* @returns {[]}
*/
-export function getSublistWithIds(
+export function getSublistWithIds(
idList: Array,
- originalList: Array<{key: string, ...T}>,
-): Array<{key: string, ...T} | null> {
- const subList = [];
+ originalList: Array,
+) {
+ const subList: Array = [];
for (let i = 0; i < idList.length; i += 1) {
subList.push(null);
}
@@ -45,26 +60,10 @@ export function getSublistWithIds(
if (idList.includes(item.key)) {
subList[idList.indexOf(item.key)] = item;
itemsAdded += 1;
- if (itemsAdded === idList.length) break;
+ if (itemsAdded === idList.length) {
+ break;
+ }
}
}
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,
- );
- }
-}
diff --git a/src/utils/URLHandler.js b/src/utils/URLHandler.ts
similarity index 89%
rename from src/utils/URLHandler.js
rename to src/utils/URLHandler.ts
index 8c89dbf..15764e5 100644
--- a/src/utils/URLHandler.js
+++ b/src/utils/URLHandler.ts
@@ -17,20 +17,18 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
import {Linking} from 'react-native';
export type ParsedUrlDataType = {
- route: string,
- data: {[key: string]: string},
+ route: string;
+ data: {[key: string]: string};
};
export type ParsedUrlCallbackType = (parsedData: ParsedUrlDataType) => void;
type RawParsedUrlDataType = {
- path: string,
- queryParams: {[key: string]: string},
+ path: string;
+ queryParams: {[key: string]: string};
};
/**
@@ -69,7 +67,7 @@ export default class URLHandler {
let parsedData: RawParsedUrlDataType | null = null;
const urlNoScheme = url.replace(URLHandler.SCHEME, '');
if (urlNoScheme != null) {
- const params = {};
+ const params: {[key: string]: string} = {};
const [path, fullParamsString] = urlNoScheme.split('?');
if (fullParamsString != null) {
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;
}
@@ -99,10 +99,11 @@ export default class URLHandler {
if (rawParsedUrlData != null) {
const {path} = rawParsedUrlData;
const {queryParams} = rawParsedUrlData;
- if (URLHandler.isClubInformationLink(path))
+ if (URLHandler.isClubInformationLink(path)) {
parsedData = URLHandler.generateClubInformationData(queryParams);
- else if (URLHandler.isPlanningInformationLink(path))
+ } else if (URLHandler.isPlanningInformationLink(path)) {
parsedData = URLHandler.generatePlanningInformationData(queryParams);
+ }
}
return parsedData;
@@ -145,15 +146,16 @@ export default class URLHandler {
* @returns {null|{route: string, data: {clubId: number}}}
*/
static generateClubInformationData(params: {
- [key: string]: string,
+ [key: string]: string;
}): ParsedUrlDataType | null {
if (params.id != null) {
const id = parseInt(params.id, 10);
- if (!Number.isNaN(id))
+ if (!Number.isNaN(id)) {
return {
route: URLHandler.CLUB_INFO_ROUTE,
data: {clubId: id.toString()},
};
+ }
}
return null;
}
@@ -165,7 +167,7 @@ export default class URLHandler {
* @returns {null|{route: string, data: {clubId: number}}}
*/
static generatePlanningInformationData(params: {
- [key: string]: string,
+ [key: string]: string;
}): ParsedUrlDataType | null {
if (params.id != null) {
const id = parseInt(params.id, 10);
@@ -201,7 +203,9 @@ export default class URLHandler {
onUrl = ({url}: {url: string}) => {
if (url != null) {
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
*/
- onInitialUrl = (url: ?string) => {
+ onInitialUrl = (url: string | null) => {
if (url != null) {
const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
- if (data != null) this.onInitialURLParsed(data);
+ if (data != null) {
+ this.onInitialURLParsed(data);
+ }
}
};
}
diff --git a/src/utils/Services.js b/src/utils/Utils.ts
similarity index 58%
rename from src/utils/Services.js
rename to src/utils/Utils.ts
index 0d174a9..b0c7c13 100644
--- a/src/utils/Services.js
+++ b/src/utils/Utils.ts
@@ -17,22 +17,23 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
+import {Platform, StatusBar} from 'react-native';
+import ThemeManager from '../managers/ThemeManager';
/**
- * Gets the given services list without items of the given ids
- *
- * @param idList The ids of items to remove
- * @param sourceList The item list to use as source
- * @returns {[]}
+ * Updates status bar content color if on iOS only,
+ * as the android status bar is always set to black.
*/
-export default function getStrippedServicesList(
- idList: Array,
- sourceList: Array<{key: string, ...T}>,
-): Array<{key: string, ...T}> {
- const newArray = [];
- sourceList.forEach((item: {key: string, ...T}) => {
- if (!idList.includes(item.key)) newArray.push(item);
- });
- return newArray;
+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,
+ );
+ }
}
diff --git a/src/utils/WebData.js b/src/utils/WebData.ts
similarity index 73%
rename from src/utils/WebData.js
rename to src/utils/WebData.ts
index dba16d6..44e68d7 100644
--- a/src/utils/WebData.js
+++ b/src/utils/WebData.ts
@@ -17,8 +17,6 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
export const ERROR_TYPE = {
SUCCESS: 0,
BAD_CREDENTIALS: 1,
@@ -34,15 +32,14 @@ export const ERROR_TYPE = {
};
export type ApiDataLoginType = {
- token: string,
+ token: string;
};
-// eslint-disable-next-line flowtype/no-weak-types
export type ApiGenericDataType = {[key: string]: any};
-type ApiResponseType = {
- error: number,
- data: ApiGenericDataType,
+type ApiResponseType = {
+ error: number;
+ data: T;
};
const API_ENDPOINT = 'https://www.amicale-insat.fr/api/';
@@ -55,11 +52,10 @@ const API_ENDPOINT = 'https://www.amicale-insat.fr/api/';
* @param response
* @returns {boolean}
*/
-export function isApiResponseValid(response: ApiResponseType): boolean {
+export function isApiResponseValid(response: ApiResponseType): boolean {
return (
response != null &&
response.error != null &&
- typeof response.error === 'number' &&
response.data != null &&
typeof response.data === 'object'
);
@@ -76,18 +72,17 @@ export function isApiResponseValid(response: ApiResponseType): boolean {
* @param params The params to use for this request
* @returns {Promise}
*/
-export async function apiRequest(
+export async function apiRequest(
path: string,
method: string,
- params?: {...},
-): Promise {
+ params?: object,
+): Promise {
return new Promise(
- (
- resolve: (data: ApiGenericDataType) => void,
- reject: (error: number) => void,
- ) => {
+ (resolve: (data: T) => void, reject: (error: number) => void) => {
let requestParams = {};
- if (params != null) requestParams = {...params};
+ if (params != null) {
+ requestParams = {...params};
+ }
fetch(API_ENDPOINT + path, {
method,
headers: new Headers({
@@ -96,14 +91,20 @@ export async function apiRequest(
}),
body: JSON.stringify(requestParams),
})
- .then(async (response: Response): Promise =>
- response.json(),
+ .then(
+ async (response: Response): Promise> =>
+ response.json(),
)
- .then((response: ApiResponseType) => {
+ .then((response: ApiResponseType) => {
if (isApiResponseValid(response)) {
- if (response.error === ERROR_TYPE.SUCCESS) resolve(response.data);
- else reject(response.error);
- } else reject(ERROR_TYPE.SERVER_ERROR);
+ if (response.error === ERROR_TYPE.SUCCESS) {
+ resolve(response.data);
+ } else {
+ reject(response.error);
+ }
+ } else {
+ reject(ERROR_TYPE.SERVER_ERROR);
+ }
})
.catch((): void => reject(ERROR_TYPE.CONNECTION_ERROR));
},
@@ -121,14 +122,10 @@ export async function apiRequest(
* @param url The urls to fetch data from
* @return Promise
*/
-// eslint-disable-next-line flowtype/no-weak-types
export async function readData(url: string): Promise {
- // eslint-disable-next-line flowtype/no-weak-types
return new Promise((resolve: (response: any) => void, reject: () => void) => {
fetch(url)
- // eslint-disable-next-line flowtype/no-weak-types
.then(async (response: Response): Promise => response.json())
- // eslint-disable-next-line flowtype/no-weak-types
.then((data: any): void => resolve(data))
.catch((): void => reject());
});
diff --git a/src/utils/withCollapsible.js b/src/utils/withCollapsible.tsx
similarity index 76%
rename from src/utils/withCollapsible.js
rename to src/utils/withCollapsible.tsx
index 0c66383..4d537cd 100644
--- a/src/utils/withCollapsible.js
+++ b/src/utils/withCollapsible.tsx
@@ -17,8 +17,6 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
import * as React from 'react';
import {useCollapsibleStack} from 'react-navigation-collapsible';
@@ -35,18 +33,12 @@ import {useCollapsibleStack} from 'react-navigation-collapsible';
* @param Component The component to use Collapsible with
* @returns {React.ComponentType}
*/
-export default function withCollapsible(
- // eslint-disable-next-line flowtype/no-weak-types
- Component: React.ComponentType,
- // eslint-disable-next-line flowtype/no-weak-types
-): React$AbstractComponent {
- // eslint-disable-next-line flowtype/no-weak-types
- return React.forwardRef((props: any, ref: any): React.Node => {
+export default function withCollapsible(Component: React.ComponentType) {
+ return React.forwardRef((props: any, ref: any) => {
return (
);