Browse Source

Update utility files to use TypeScript

Arnaud Vergnet 3 years ago
parent
commit
18ec6e0a59

+ 16
- 0
package-lock.json View File

2501
       "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.36.tgz",
2501
       "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.36.tgz",
2502
       "integrity": "sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ=="
2502
       "integrity": "sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ=="
2503
     },
2503
     },
2504
+    "@types/i18n-js": {
2505
+      "version": "3.0.3",
2506
+      "resolved": "https://registry.npmjs.org/@types/i18n-js/-/i18n-js-3.0.3.tgz",
2507
+      "integrity": "sha512-GiZzazvxQ5j+EA4Zf4MtDsSaokAR/gW7FxxTlHi2p2xKFUhwAUT0B/MB8WL77P1TcqAO3MefWorFFyZS8F7s0Q==",
2508
+      "dev": true
2509
+    },
2504
     "@types/istanbul-lib-coverage": {
2510
     "@types/istanbul-lib-coverage": {
2505
       "version": "2.0.3",
2511
       "version": "2.0.3",
2506
       "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
2512
       "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
2602
         "@types/react": "*"
2608
         "@types/react": "*"
2603
       }
2609
       }
2604
     },
2610
     },
2611
+    "@types/react-native-vector-icons": {
2612
+      "version": "6.4.6",
2613
+      "resolved": "https://registry.npmjs.org/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.6.tgz",
2614
+      "integrity": "sha512-lAyxNfMd5L1xZvXWsGcJmNegDf61TAp40uL6ashNNWj9W3IrDJO59L9+9inh0Y2MsEZpLTdxzVU8Unb4/0FQng==",
2615
+      "dev": true,
2616
+      "requires": {
2617
+        "@types/react": "*",
2618
+        "@types/react-native": "*"
2619
+      }
2620
+    },
2605
     "@types/react-test-renderer": {
2621
     "@types/react-test-renderer": {
2606
       "version": "16.9.3",
2622
       "version": "16.9.3",
2607
       "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-16.9.3.tgz",
2623
       "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-16.9.3.tgz",

+ 2
- 0
package.json View File

66
     "@babel/core": "^7.11.0",
66
     "@babel/core": "^7.11.0",
67
     "@babel/runtime": "^7.11.0",
67
     "@babel/runtime": "^7.11.0",
68
     "@react-native-community/eslint-config": "^1.1.0",
68
     "@react-native-community/eslint-config": "^1.1.0",
69
+    "@types/i18n-js": "^3.0.3",
70
+    "@types/react-native-vector-icons": "^6.4.6",
69
     "@types/jest": "^25.2.3",
71
     "@types/jest": "^25.2.3",
70
     "@types/react-native": "^0.63.2",
72
     "@types/react-native": "^0.63.2",
71
     "@types/react-test-renderer": "^16.9.2",
73
     "@types/react-test-renderer": "^16.9.2",

src/managers/AprilFoolsManager.js → src/managers/AprilFoolsManager.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 import type {ProxiwashMachineType} from '../screens/Proxiwash/ProxiwashScreen';
20
 import type {ProxiwashMachineType} from '../screens/Proxiwash/ProxiwashScreen';
23
-import type {CustomThemeType} from './ThemeManager';
24
 import type {RuFoodCategoryType} from '../screens/Services/SelfMenuScreen';
21
 import type {RuFoodCategoryType} from '../screens/Services/SelfMenuScreen';
25
 
22
 
26
 /**
23
 /**
57
    * @returns {ThemeManager}
54
    * @returns {ThemeManager}
58
    */
55
    */
59
   static getInstance(): AprilFoolsManager {
56
   static getInstance(): AprilFoolsManager {
60
-    if (AprilFoolsManager.instance == null)
57
+    if (AprilFoolsManager.instance == null) {
61
       AprilFoolsManager.instance = new AprilFoolsManager();
58
       AprilFoolsManager.instance = new AprilFoolsManager();
59
+    }
62
     return AprilFoolsManager.instance;
60
     return AprilFoolsManager.instance;
63
   }
61
   }
64
 
62
 
130
    * @param currentTheme
128
    * @param currentTheme
131
    * @returns {{colors: {textDisabled: string, agendaDayTextColor: string, surface: string, background: string, dividerBackground: string, accent: string, agendaBackgroundColor: string, tabIcon: string, card: string, primary: string}}}
129
    * @returns {{colors: {textDisabled: string, agendaDayTextColor: string, surface: string, background: string, dividerBackground: string, accent: string, agendaBackgroundColor: string, tabIcon: string, card: string, primary: string}}}
132
    */
130
    */
133
-  static getAprilFoolsTheme(currentTheme: CustomThemeType): CustomThemeType {
131
+  static getAprilFoolsTheme(
132
+    currentTheme: ReactNativePaper.Theme,
133
+  ): ReactNativePaper.Theme {
134
     return {
134
     return {
135
       ...currentTheme,
135
       ...currentTheme,
136
       colors: {
136
       colors: {

+ 1
- 1
src/managers/AsyncStorageManager.ts View File

198
    * @param key
198
    * @param key
199
    * @returns {{...}}
199
    * @returns {{...}}
200
    */
200
    */
201
-  static getObject(key: string): object | Array<any> {
201
+  static getObject<T>(key: string): T {
202
     return JSON.parse(AsyncStorageManager.getString(key));
202
     return JSON.parse(AsyncStorageManager.getString(key));
203
   }
203
   }
204
 
204
 

src/managers/ConnectionManager.js → src/managers/ConnectionManager.ts View File

20
 // @flow
20
 // @flow
21
 
21
 
22
 import * as Keychain from 'react-native-keychain';
22
 import * as Keychain from 'react-native-keychain';
23
-import type {ApiDataLoginType, ApiGenericDataType} from '../utils/WebData';
23
+import type {ApiDataLoginType} from '../utils/WebData';
24
 import {apiRequest, ERROR_TYPE} from '../utils/WebData';
24
 import {apiRequest, ERROR_TYPE} from '../utils/WebData';
25
 
25
 
26
 /**
26
 /**
40
 export default class ConnectionManager {
40
 export default class ConnectionManager {
41
   static instance: ConnectionManager | null = null;
41
   static instance: ConnectionManager | null = null;
42
 
42
 
43
-  #email: string;
44
-
45
-  #token: string | null;
43
+  private token: string | null;
46
 
44
 
47
   constructor() {
45
   constructor() {
48
-    this.#token = null;
46
+    this.token = null;
49
   }
47
   }
50
 
48
 
51
   /**
49
   /**
54
    * @returns {ConnectionManager}
52
    * @returns {ConnectionManager}
55
    */
53
    */
56
   static getInstance(): ConnectionManager {
54
   static getInstance(): ConnectionManager {
57
-    if (ConnectionManager.instance == null)
55
+    if (ConnectionManager.instance == null) {
58
       ConnectionManager.instance = new ConnectionManager();
56
       ConnectionManager.instance = new ConnectionManager();
57
+    }
59
     return ConnectionManager.instance;
58
     return ConnectionManager.instance;
60
   }
59
   }
61
 
60
 
65
    * @returns {string | null}
64
    * @returns {string | null}
66
    */
65
    */
67
   getToken(): string | null {
66
   getToken(): string | null {
68
-    return this.#token;
67
+    return this.token;
69
   }
68
   }
70
 
69
 
71
   /**
70
   /**
77
     return new Promise(
76
     return new Promise(
78
       (resolve: (token: string) => void, reject: () => void) => {
77
       (resolve: (token: string) => void, reject: () => void) => {
79
         const token = this.getToken();
78
         const token = this.getToken();
80
-        if (token != null) resolve(token);
81
-        else {
79
+        if (token != null) {
80
+          resolve(token);
81
+        } else {
82
           Keychain.getInternetCredentials(SERVER_NAME)
82
           Keychain.getInternetCredentials(SERVER_NAME)
83
             .then((data: Keychain.UserCredentials | false) => {
83
             .then((data: Keychain.UserCredentials | false) => {
84
-              if (
85
-                data != null &&
86
-                data.password != null &&
87
-                typeof data.password === 'string'
88
-              ) {
89
-                this.#token = data.password;
90
-                resolve(this.#token);
91
-              } else reject();
84
+              if (data && data.password != null) {
85
+                this.token = data.password;
86
+                resolve(this.token);
87
+              } else {
88
+                reject();
89
+              }
92
             })
90
             })
93
             .catch((): void => reject());
91
             .catch((): void => reject());
94
         }
92
         }
116
     return new Promise((resolve: () => void, reject: () => void) => {
114
     return new Promise((resolve: () => void, reject: () => void) => {
117
       Keychain.setInternetCredentials(SERVER_NAME, 'token', token)
115
       Keychain.setInternetCredentials(SERVER_NAME, 'token', token)
118
         .then(() => {
116
         .then(() => {
119
-          this.#token = token;
120
-          this.#email = email;
117
+          this.token = token;
121
           resolve();
118
           resolve();
122
         })
119
         })
123
         .catch((): void => reject());
120
         .catch((): void => reject());
133
     return new Promise((resolve: () => void, reject: () => void) => {
130
     return new Promise((resolve: () => void, reject: () => void) => {
134
       Keychain.resetInternetCredentials(SERVER_NAME)
131
       Keychain.resetInternetCredentials(SERVER_NAME)
135
         .then(() => {
132
         .then(() => {
136
-          this.#token = null;
133
+          this.token = null;
137
           resolve();
134
           resolve();
138
         })
135
         })
139
         .catch((): void => reject());
136
         .catch((): void => reject());
156
           email,
153
           email,
157
           password,
154
           password,
158
         };
155
         };
159
-        apiRequest(AUTH_PATH, 'POST', data)
156
+        apiRequest<ApiDataLoginType>(AUTH_PATH, 'POST', data)
160
           .then((response: ApiDataLoginType) => {
157
           .then((response: ApiDataLoginType) => {
161
             if (response.token != null) {
158
             if (response.token != null) {
162
               this.saveLogin(email, response.token)
159
               this.saveLogin(email, response.token)
163
                 .then((): void => resolve())
160
                 .then((): void => resolve())
164
                 .catch((): void => reject(ERROR_TYPE.TOKEN_SAVE));
161
                 .catch((): void => reject(ERROR_TYPE.TOKEN_SAVE));
165
-            } else reject(ERROR_TYPE.SERVER_ERROR);
162
+            } else {
163
+              reject(ERROR_TYPE.SERVER_ERROR);
164
+            }
166
           })
165
           })
167
           .catch((error: number): void => reject(error));
166
           .catch((error: number): void => reject(error));
168
       },
167
       },
176
    * @param params
175
    * @param params
177
    * @returns Promise<ApiGenericDataType>
176
    * @returns Promise<ApiGenericDataType>
178
    */
177
    */
179
-  async authenticatedRequest(
178
+  async authenticatedRequest<T>(
180
     path: string,
179
     path: string,
181
-    params: {...},
182
-  ): Promise<ApiGenericDataType> {
180
+    params: {[key: string]: any},
181
+  ): Promise<T> {
183
     return new Promise(
182
     return new Promise(
184
-      (
185
-        resolve: (response: ApiGenericDataType) => void,
186
-        reject: (error: number) => void,
187
-      ) => {
183
+      (resolve: (response: T) => void, reject: (error: number) => void) => {
188
         if (this.getToken() !== null) {
184
         if (this.getToken() !== null) {
189
           const data = {
185
           const data = {
190
             ...params,
186
             ...params,
191
             token: this.getToken(),
187
             token: this.getToken(),
192
           };
188
           };
193
-          apiRequest(path, 'POST', data)
194
-            .then((response: ApiGenericDataType): void => resolve(response))
189
+          apiRequest<T>(path, 'POST', data)
190
+            .then((response: T): void => resolve(response))
195
             .catch((error: number): void => reject(error));
191
             .catch((error: number): void => reject(error));
196
-        } else reject(ERROR_TYPE.TOKEN_RETRIEVE);
192
+        } else {
193
+          reject(ERROR_TYPE.TOKEN_RETRIEVE);
194
+        }
197
       },
195
       },
198
     );
196
     );
199
   }
197
   }

src/managers/DashboardManager.js → src/managers/DashboardManager.ts View File

21
 
21
 
22
 import type {ServiceItemType} from './ServicesManager';
22
 import type {ServiceItemType} from './ServicesManager';
23
 import ServicesManager from './ServicesManager';
23
 import ServicesManager from './ServicesManager';
24
-import {getSublistWithIds} from '../utils/Utils';
24
+import {getSublistWithIds} from '../utils/Services';
25
 import AsyncStorageManager from './AsyncStorageManager';
25
 import AsyncStorageManager from './AsyncStorageManager';
26
 
26
 
27
 export default class DashboardManager extends ServicesManager {
27
 export default class DashboardManager extends ServicesManager {
28
   getCurrentDashboard(): Array<ServiceItemType | null> {
28
   getCurrentDashboard(): Array<ServiceItemType | null> {
29
-    const dashboardIdList = AsyncStorageManager.getObject(
29
+    const dashboardIdList = AsyncStorageManager.getObject<Array<string>>(
30
       AsyncStorageManager.PREFERENCES.dashboardItems.key,
30
       AsyncStorageManager.PREFERENCES.dashboardItems.key,
31
     );
31
     );
32
     const allDatasets = [
32
     const allDatasets = [

src/managers/DateManager.js → src/managers/DateManager.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 import i18n from 'i18n-js';
20
 import i18n from 'i18n-js';
23
 
21
 
24
 /**
22
 /**
28
 export default class DateManager {
26
 export default class DateManager {
29
   static instance: DateManager | null = null;
27
   static instance: DateManager | null = null;
30
 
28
 
31
-  daysOfWeek = [];
29
+  daysOfWeek: Array<string> = [];
32
 
30
 
33
-  monthsOfYear = [];
31
+  monthsOfYear: Array<string> = [];
34
 
32
 
35
   constructor() {
33
   constructor() {
36
     this.daysOfWeek.push(i18n.t('date.daysOfWeek.sunday')); // 0 represents sunday
34
     this.daysOfWeek.push(i18n.t('date.daysOfWeek.sunday')); // 0 represents sunday
60
    * @returns {DateManager}
58
    * @returns {DateManager}
61
    */
59
    */
62
   static getInstance(): DateManager {
60
   static getInstance(): DateManager {
63
-    if (DateManager.instance == null) DateManager.instance = new DateManager();
61
+    if (DateManager.instance == null) {
62
+      DateManager.instance = new DateManager();
63
+    }
64
     return DateManager.instance;
64
     return DateManager.instance;
65
   }
65
   }
66
 
66
 

src/managers/ServicesManager.js → src/managers/ServicesManager.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 import i18n from 'i18n-js';
20
 import i18n from 'i18n-js';
23
 import {StackNavigationProp} from '@react-navigation/stack';
21
 import {StackNavigationProp} from '@react-navigation/stack';
24
 import AvailableWebsites from '../constants/AvailableWebsites';
22
 import AvailableWebsites from '../constants/AvailableWebsites';
93
 };
91
 };
94
 
92
 
95
 export type ServiceItemType = {
93
 export type ServiceItemType = {
96
-  key: string,
97
-  title: string,
98
-  subtitle: string,
99
-  image: string,
100
-  onPress: () => void,
101
-  badgeFunction?: (dashboard: FullDashboardType) => number,
94
+  key: string;
95
+  title: string;
96
+  subtitle: string;
97
+  image: string;
98
+  onPress: () => void;
99
+  badgeFunction?: (dashboard: FullDashboardType) => number;
102
 };
100
 };
103
 
101
 
104
 export type ServiceCategoryType = {
102
 export type ServiceCategoryType = {
105
-  key: string,
106
-  title: string,
107
-  subtitle: string,
108
-  image: string | number,
109
-  content: Array<ServiceItemType>,
103
+  key: string;
104
+  title: string;
105
+  subtitle: string;
106
+  image: string | number;
107
+  content: Array<ServiceItemType>;
110
 };
108
 };
111
 
109
 
112
 export default class ServicesManager {
110
 export default class ServicesManager {
113
-  navigation: StackNavigationProp;
111
+  navigation: StackNavigationProp<any>;
114
 
112
 
115
   amicaleDataset: Array<ServiceItemType>;
113
   amicaleDataset: Array<ServiceItemType>;
116
 
114
 
122
 
120
 
123
   categoriesDataset: Array<ServiceCategoryType>;
121
   categoriesDataset: Array<ServiceCategoryType>;
124
 
122
 
125
-  constructor(nav: StackNavigationProp) {
123
+  constructor(nav: StackNavigationProp<any>) {
126
     this.navigation = nav;
124
     this.navigation = nav;
127
     this.amicaleDataset = [
125
     this.amicaleDataset = [
128
       {
126
       {
336
    * @returns {null}
334
    * @returns {null}
337
    */
335
    */
338
   onAmicaleServicePress(route: string) {
336
   onAmicaleServicePress(route: string) {
339
-    if (ConnectionManager.getInstance().isLoggedIn())
337
+    if (ConnectionManager.getInstance().isLoggedIn()) {
340
       this.navigation.navigate(route);
338
       this.navigation.navigate(route);
341
-    else this.navigation.navigate('login', {nextScreen: route});
339
+    } else {
340
+      this.navigation.navigate('login', {nextScreen: route});
341
+    }
342
   }
342
   }
343
 
343
 
344
   /**
344
   /**
348
    * @returns {Array<ServiceItemType>}
348
    * @returns {Array<ServiceItemType>}
349
    */
349
    */
350
   getAmicaleServices(excludedItems?: Array<string>): Array<ServiceItemType> {
350
   getAmicaleServices(excludedItems?: Array<string>): Array<ServiceItemType> {
351
-    if (excludedItems != null)
351
+    if (excludedItems != null) {
352
       return getStrippedServicesList(excludedItems, this.amicaleDataset);
352
       return getStrippedServicesList(excludedItems, this.amicaleDataset);
353
+    }
353
     return this.amicaleDataset;
354
     return this.amicaleDataset;
354
   }
355
   }
355
 
356
 
360
    * @returns {Array<ServiceItemType>}
361
    * @returns {Array<ServiceItemType>}
361
    */
362
    */
362
   getStudentServices(excludedItems?: Array<string>): Array<ServiceItemType> {
363
   getStudentServices(excludedItems?: Array<string>): Array<ServiceItemType> {
363
-    if (excludedItems != null)
364
+    if (excludedItems != null) {
364
       return getStrippedServicesList(excludedItems, this.studentsDataset);
365
       return getStrippedServicesList(excludedItems, this.studentsDataset);
366
+    }
365
     return this.studentsDataset;
367
     return this.studentsDataset;
366
   }
368
   }
367
 
369
 
372
    * @returns {Array<ServiceItemType>}
374
    * @returns {Array<ServiceItemType>}
373
    */
375
    */
374
   getINSAServices(excludedItems?: Array<string>): Array<ServiceItemType> {
376
   getINSAServices(excludedItems?: Array<string>): Array<ServiceItemType> {
375
-    if (excludedItems != null)
377
+    if (excludedItems != null) {
376
       return getStrippedServicesList(excludedItems, this.insaDataset);
378
       return getStrippedServicesList(excludedItems, this.insaDataset);
379
+    }
377
     return this.insaDataset;
380
     return this.insaDataset;
378
   }
381
   }
379
 
382
 
384
    * @returns {Array<ServiceItemType>}
387
    * @returns {Array<ServiceItemType>}
385
    */
388
    */
386
   getSpecialServices(excludedItems?: Array<string>): Array<ServiceItemType> {
389
   getSpecialServices(excludedItems?: Array<string>): Array<ServiceItemType> {
387
-    if (excludedItems != null)
390
+    if (excludedItems != null) {
388
       return getStrippedServicesList(excludedItems, this.specialDataset);
391
       return getStrippedServicesList(excludedItems, this.specialDataset);
392
+    }
389
     return this.specialDataset;
393
     return this.specialDataset;
390
   }
394
   }
391
 
395
 
396
    * @returns {Array<ServiceCategoryType>}
400
    * @returns {Array<ServiceCategoryType>}
397
    */
401
    */
398
   getCategories(excludedItems?: Array<string>): Array<ServiceCategoryType> {
402
   getCategories(excludedItems?: Array<string>): Array<ServiceCategoryType> {
399
-    if (excludedItems != null)
403
+    if (excludedItems != null) {
400
       return getStrippedServicesList(excludedItems, this.categoriesDataset);
404
       return getStrippedServicesList(excludedItems, this.categoriesDataset);
405
+    }
401
     return this.categoriesDataset;
406
     return this.categoriesDataset;
402
   }
407
   }
403
 }
408
 }

src/utils/AutoHideHandler.js → src/utils/AutoHideHandler.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
20
+import {NativeScrollEvent, NativeSyntheticEvent} from 'react-native';
21
 
21
 
22
 const speedOffset = 5;
22
 const speedOffset = 5;
23
 
23
 
24
 type ListenerFunctionType = (shouldHide: boolean) => void;
24
 type ListenerFunctionType = (shouldHide: boolean) => void;
25
 
25
 
26
-export type OnScrollType = {
27
-  nativeEvent: {
28
-    contentInset: {bottom: number, left: number, right: number, top: number},
29
-    contentOffset: {x: number, y: number},
30
-    contentSize: {height: number, width: number},
31
-    layoutMeasurement: {height: number, width: number},
32
-    zoomScale: number,
33
-  },
34
-};
35
-
36
 /**
26
 /**
37
  * Class used to detect when to show or hide a component based on scrolling
27
  * Class used to detect when to show or hide a component based on scrolling
38
  */
28
  */
46
   constructor(startHidden: boolean) {
36
   constructor(startHidden: boolean) {
47
     this.listeners = [];
37
     this.listeners = [];
48
     this.isHidden = startHidden;
38
     this.isHidden = startHidden;
39
+    this.lastOffset = 0;
49
   }
40
   }
50
 
41
 
51
   /**
42
   /**
84
    *
75
    *
85
    * @param event The scroll event generated by the animated component onScroll prop
76
    * @param event The scroll event generated by the animated component onScroll prop
86
    */
77
    */
87
-  onScroll(event: OnScrollType) {
78
+  onScroll(event: NativeSyntheticEvent<NativeScrollEvent>) {
88
     const {nativeEvent} = event;
79
     const {nativeEvent} = event;
89
     const speed =
80
     const speed =
90
       nativeEvent.contentOffset.y < 0
81
       nativeEvent.contentOffset.y < 0

src/utils/CollapsibleUtils.js → src/utils/CollapsibleUtils.tsx View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 import * as React from 'react';
20
 import * as React from 'react';
23
 import {useTheme} from 'react-native-paper';
21
 import {useTheme} from 'react-native-paper';
24
 import {createCollapsibleStack} from 'react-navigation-collapsible';
22
 import {createCollapsibleStack} from 'react-navigation-collapsible';
25
 import StackNavigator, {StackNavigationOptions} from '@react-navigation/stack';
23
 import StackNavigator, {StackNavigationOptions} from '@react-navigation/stack';
24
+import {StackNavigationState} from '@react-navigation/native';
25
+import {StackNavigationEventMap} from '@react-navigation/stack/lib/typescript/src/types';
26
+
27
+type StackNavigatorType = import('@react-navigation/native').TypedNavigator<
28
+  Record<string, object | undefined>,
29
+  StackNavigationState,
30
+  StackNavigationOptions,
31
+  StackNavigationEventMap,
32
+  typeof StackNavigator
33
+>;
26
 
34
 
27
 /**
35
 /**
28
  * Creates a navigation stack with the collapsible library, allowing the header to collapse on scroll.
36
  * Creates a navigation stack with the collapsible library, allowing the header to collapse on scroll.
40
  * @param headerColor The color of the header. Uses default color if not specified
48
  * @param headerColor The color of the header. Uses default color if not specified
41
  * @returns {JSX.Element}
49
  * @returns {JSX.Element}
42
  */
50
  */
43
-export function createScreenCollapsibleStack(
51
+export function CreateScreenCollapsibleStack(
44
   name: string,
52
   name: string,
45
-  Stack: StackNavigator,
46
-  // eslint-disable-next-line flowtype/no-weak-types
53
+  Stack: StackNavigatorType,
47
   component: React.ComponentType<any>,
54
   component: React.ComponentType<any>,
48
   title: string,
55
   title: string,
49
-  useNativeDriver?: boolean,
50
-  options?: StackNavigationOptions,
56
+  useNativeDriver: boolean = true,
57
+  options: StackNavigationOptions = {},
51
   headerColor?: string,
58
   headerColor?: string,
52
-): React.Node {
59
+) {
53
   const {colors} = useTheme();
60
   const {colors} = useTheme();
54
-  const screenOptions = options != null ? options : {};
55
   return createCollapsibleStack(
61
   return createCollapsibleStack(
56
     <Stack.Screen
62
     <Stack.Screen
57
       name={name}
63
       name={name}
61
         headerStyle: {
67
         headerStyle: {
62
           backgroundColor: headerColor != null ? headerColor : colors.surface,
68
           backgroundColor: headerColor != null ? headerColor : colors.surface,
63
         },
69
         },
64
-        ...screenOptions,
70
+        ...options,
65
       }}
71
       }}
66
     />,
72
     />,
67
     {
73
     {
68
       collapsedColor: headerColor != null ? headerColor : colors.surface,
74
       collapsedColor: headerColor != null ? headerColor : colors.surface,
69
-      useNativeDriver: useNativeDriver != null ? useNativeDriver : true, // native driver does not work with webview
75
+      useNativeDriver: useNativeDriver, // native driver does not work with webview
70
     },
76
     },
71
   );
77
   );
72
 }
78
 }
85
  */
91
  */
86
 export function getWebsiteStack(
92
 export function getWebsiteStack(
87
   name: string,
93
   name: string,
88
-  Stack: StackNavigator,
89
-  // eslint-disable-next-line flowtype/no-weak-types
94
+  Stack: StackNavigatorType,
90
   component: React.ComponentType<any>,
95
   component: React.ComponentType<any>,
91
   title: string,
96
   title: string,
92
-): React.Node {
93
-  return createScreenCollapsibleStack(name, Stack, component, title, false);
97
+) {
98
+  return CreateScreenCollapsibleStack(name, Stack, component, title, false);
94
 }
99
 }

src/utils/EquipmentBooking.js → src/utils/EquipmentBooking.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 import i18n from 'i18n-js';
20
 import i18n from 'i18n-js';
23
 import type {DeviceType} from '../screens/Amicale/Equipment/EquipmentListScreen';
21
 import type {DeviceType} from '../screens/Amicale/Equipment/EquipmentListScreen';
24
 import DateManager from '../managers/DateManager';
22
 import DateManager from '../managers/DateManager';
25
-import type {CustomThemeType} from '../managers/ThemeManager';
26
 import type {MarkedDatesObjectType} from '../screens/Amicale/Equipment/EquipmentRentScreen';
23
 import type {MarkedDatesObjectType} from '../screens/Amicale/Equipment/EquipmentRentScreen';
27
 
24
 
28
 /**
25
 /**
56
   let isAvailable = true;
53
   let isAvailable = true;
57
   const today = getCurrentDay();
54
   const today = getCurrentDay();
58
   const dates = item.booked_at;
55
   const dates = item.booked_at;
59
-  dates.forEach((date: {begin: string, end: string}) => {
56
+  dates.forEach((date: {begin: string; end: string}) => {
60
     const start = new Date(date.begin);
57
     const start = new Date(date.begin);
61
     const end = new Date(date.end);
58
     const end = new Date(date.end);
62
-    if (!(today < start || today > end)) isAvailable = false;
59
+    if (!(today < start || today > end)) {
60
+      isAvailable = false;
61
+    }
63
   });
62
   });
64
   return isAvailable;
63
   return isAvailable;
65
 }
64
 }
73
 export function getFirstEquipmentAvailability(item: DeviceType): Date {
72
 export function getFirstEquipmentAvailability(item: DeviceType): Date {
74
   let firstAvailability = getCurrentDay();
73
   let firstAvailability = getCurrentDay();
75
   const dates = item.booked_at;
74
   const dates = item.booked_at;
76
-  dates.forEach((date: {begin: string, end: string}) => {
75
+  dates.forEach((date: {begin: string; end: string}) => {
77
     const start = new Date(date.begin);
76
     const start = new Date(date.begin);
78
     const end = new Date(date.end);
77
     const end = new Date(date.end);
79
     end.setDate(end.getDate() + 1);
78
     end.setDate(end.getDate() + 1);
80
-    if (firstAvailability >= start) firstAvailability = end;
79
+    if (firstAvailability >= start) {
80
+      firstAvailability = end;
81
+    }
81
   });
82
   });
82
   return firstAvailability;
83
   return firstAvailability;
83
 }
84
 }
93
   const monthDelta = date.getUTCMonth() - today.getUTCMonth();
94
   const monthDelta = date.getUTCMonth() - today.getUTCMonth();
94
   const dayDelta = date.getUTCDate() - today.getUTCDate();
95
   const dayDelta = date.getUTCDate() - today.getUTCDate();
95
   let translatedString = i18n.t('screens.equipment.today');
96
   let translatedString = i18n.t('screens.equipment.today');
96
-  if (yearDelta > 0)
97
+  if (yearDelta > 0) {
97
     translatedString = i18n.t('screens.equipment.otherYear', {
98
     translatedString = i18n.t('screens.equipment.otherYear', {
98
       date: date.getDate(),
99
       date: date.getDate(),
99
       month: DateManager.getInstance().getMonthsOfYear()[date.getMonth()],
100
       month: DateManager.getInstance().getMonthsOfYear()[date.getMonth()],
100
       year: date.getFullYear(),
101
       year: date.getFullYear(),
101
     });
102
     });
102
-  else if (monthDelta > 0)
103
+  } else if (monthDelta > 0) {
103
     translatedString = i18n.t('screens.equipment.otherMonth', {
104
     translatedString = i18n.t('screens.equipment.otherMonth', {
104
       date: date.getDate(),
105
       date: date.getDate(),
105
       month: DateManager.getInstance().getMonthsOfYear()[date.getMonth()],
106
       month: DateManager.getInstance().getMonthsOfYear()[date.getMonth()],
106
     });
107
     });
107
-  else if (dayDelta > 1)
108
+  } else if (dayDelta > 1) {
108
     translatedString = i18n.t('screens.equipment.thisMonth', {
109
     translatedString = i18n.t('screens.equipment.thisMonth', {
109
       date: date.getDate(),
110
       date: date.getDate(),
110
     });
111
     });
111
-  else if (dayDelta === 1)
112
+  } else if (dayDelta === 1) {
112
     translatedString = i18n.t('screens.equipment.tomorrow');
113
     translatedString = i18n.t('screens.equipment.tomorrow');
114
+  }
113
 
115
 
114
   return translatedString;
116
   return translatedString;
115
 }
117
 }
162
     (direction === 1 && date < limit) ||
164
     (direction === 1 && date < limit) ||
163
     (direction === -1 && date > limit)
165
     (direction === -1 && date > limit)
164
   ) {
166
   ) {
165
-    if (direction === 1) validRange.push(getISODate(date));
166
-    else validRange.unshift(getISODate(date));
167
+    if (direction === 1) {
168
+      validRange.push(getISODate(date));
169
+    } else {
170
+      validRange.unshift(getISODate(date));
171
+    }
167
     date.setDate(date.getDate() + direction);
172
     date.setDate(date.getDate() + direction);
168
   }
173
   }
169
   return validRange;
174
   return validRange;
180
  */
185
  */
181
 export function generateMarkedDates(
186
 export function generateMarkedDates(
182
   isSelection: boolean,
187
   isSelection: boolean,
183
-  theme: CustomThemeType,
188
+  theme: ReactNativePaper.Theme,
184
   range: Array<string>,
189
   range: Array<string>,
185
 ): MarkedDatesObjectType {
190
 ): MarkedDatesObjectType {
186
-  const markedDates = {};
191
+  const markedDates: {
192
+    [key: string]: {
193
+      startingDay: boolean;
194
+      endingDay: boolean;
195
+      color: string;
196
+    };
197
+  } = {};
187
   for (let i = 0; i < range.length; i += 1) {
198
   for (let i = 0; i < range.length; i += 1) {
188
     const isStart = i === 0;
199
     const isStart = i === 0;
189
     const isEnd = i === range.length - 1;
200
     const isEnd = i === range.length - 1;
190
     let color;
201
     let color;
191
-    if (isSelection && (isStart || isEnd)) color = theme.colors.primary;
192
-    else if (isSelection) color = theme.colors.danger;
193
-    else color = theme.colors.textDisabled;
202
+    if (isSelection && (isStart || isEnd)) {
203
+      color = theme.colors.primary;
204
+    } else if (isSelection) {
205
+      color = theme.colors.danger;
206
+    } else {
207
+      color = theme.colors.textDisabled;
208
+    }
194
     markedDates[range[i]] = {
209
     markedDates[range[i]] = {
195
       startingDay: isStart,
210
       startingDay: isStart,
196
       endingDay: isEnd,
211
       endingDay: isEnd,

src/utils/Home.js → src/utils/Home.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 import {stringToDate} from './Planning';
20
 import {stringToDate} from './Planning';
23
 import type {PlanningEventType} from './Planning';
21
 import type {PlanningEventType} from './Planning';
24
 
22
 
29
  */
27
  */
30
 export function getTodayEventTimeLimit(): Date {
28
 export function getTodayEventTimeLimit(): Date {
31
   const now = new Date();
29
   const now = new Date();
32
-  if (now.getDay() === 4)
30
+  if (now.getDay() === 4) {
33
     // Thursday
31
     // Thursday
34
     now.setHours(11, 30, 0);
32
     now.setHours(11, 30, 0);
35
-  else if (now.getDay() === 6 || now.getDay() === 0)
33
+  } else if (now.getDay() === 6 || now.getDay() === 0) {
36
     // Weekend
34
     // Weekend
37
     now.setHours(0, 0, 0);
35
     now.setHours(0, 0, 0);
38
-  else now.setHours(17, 30, 0);
36
+  } else {
37
+    now.setHours(17, 30, 0);
38
+  }
39
   return now;
39
   return now;
40
 }
40
 }
41
 
41
 
50
   events: Array<PlanningEventType>,
50
   events: Array<PlanningEventType>,
51
   limit: Date,
51
   limit: Date,
52
 ): Array<PlanningEventType> {
52
 ): Array<PlanningEventType> {
53
-  const validEvents = [];
53
+  const validEvents: Array<PlanningEventType> = [];
54
   events.forEach((event: PlanningEventType) => {
54
   events.forEach((event: PlanningEventType) => {
55
     const startDate = stringToDate(event.date_begin);
55
     const startDate = stringToDate(event.date_begin);
56
     if (startDate != null && startDate >= limit) {
56
     if (startDate != null && startDate >= limit) {
68
 export function getFutureEvents(
68
 export function getFutureEvents(
69
   events: Array<PlanningEventType>,
69
   events: Array<PlanningEventType>,
70
 ): Array<PlanningEventType> {
70
 ): Array<PlanningEventType> {
71
-  const validEvents = [];
71
+  const validEvents: Array<PlanningEventType> = [];
72
   const now = new Date();
72
   const now = new Date();
73
   events.forEach((event: PlanningEventType) => {
73
   events.forEach((event: PlanningEventType) => {
74
     const startDate = stringToDate(event.date_begin);
74
     const startDate = stringToDate(event.date_begin);
75
-    if (startDate != null && startDate > now) validEvents.push(event);
75
+    if (startDate != null && startDate > now) {
76
+      validEvents.push(event);
77
+    }
76
   });
78
   });
77
   return validEvents;
79
   return validEvents;
78
 }
80
 }
92
       events,
94
       events,
93
       getTodayEventTimeLimit(),
95
       getTodayEventTimeLimit(),
94
     );
96
     );
95
-    if (eventsAfterLimit.length > 0) [displayEvent] = eventsAfterLimit;
96
-    else [displayEvent] = events;
97
-  } else if (events.length === 1) [displayEvent] = events;
97
+    if (eventsAfterLimit.length > 0) {
98
+      [displayEvent] = eventsAfterLimit;
99
+    } else {
100
+      [displayEvent] = events;
101
+    }
102
+  } else if (events.length === 1) {
103
+    [displayEvent] = events;
104
+  }
98
   return displayEvent;
105
   return displayEvent;
99
 }
106
 }

src/utils/Locales.js → src/utils/Locales.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 import i18n from 'i18n-js';
20
 import i18n from 'i18n-js';
23
 import * as RNLocalize from 'react-native-localize';
21
 import * as RNLocalize from 'react-native-localize';
24
 
22
 
28
 const initLocales = () => {
26
 const initLocales = () => {
29
   i18n.fallbacks = true;
27
   i18n.fallbacks = true;
30
   i18n.translations = {fr, en};
28
   i18n.translations = {fr, en};
31
-  i18n.locale = RNLocalize.findBestAvailableLanguage([
32
-    'en',
33
-    'fr',
34
-  ]).languageTag;
35
-}
29
+  const bestLanguage = RNLocalize.findBestAvailableLanguage(['en', 'fr']);
30
+  i18n.locale = bestLanguage ? bestLanguage.languageTag : 'en';
31
+};
36
 export default initLocales;
32
 export default initLocales;

src/utils/Notifications.js → src/utils/Notifications.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 import {
20
 import {
23
   checkNotifications,
21
   checkNotifications,
24
   requestNotifications,
22
   requestNotifications,
41
 export async function askPermissions(): Promise<void> {
39
 export async function askPermissions(): Promise<void> {
42
   return new Promise((resolve: () => void, reject: () => void) => {
40
   return new Promise((resolve: () => void, reject: () => void) => {
43
     checkNotifications().then(({status}: {status: string}) => {
41
     checkNotifications().then(({status}: {status: string}) => {
44
-      if (status === RESULTS.GRANTED) resolve();
45
-      else if (status === RESULTS.BLOCKED) reject();
46
-      else {
47
-        requestNotifications().then((result: {status: string}) => {
48
-          if (result.status === RESULTS.GRANTED) resolve();
49
-          else reject();
42
+      if (status === RESULTS.GRANTED) {
43
+        resolve();
44
+      } else if (status === RESULTS.BLOCKED) {
45
+        reject();
46
+      } else {
47
+        requestNotifications([]).then((result: {status: string}) => {
48
+          if (result.status === RESULTS.GRANTED) {
49
+            resolve();
50
+          } else {
51
+            reject();
52
+          }
50
         });
53
         });
51
       }
54
       }
52
     });
55
     });

src/utils/Planning.js → src/utils/Planning.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 export type PlanningEventType = {
20
 export type PlanningEventType = {
23
-  id: number,
24
-  title: string,
25
-  date_begin: string,
26
-  club: string,
27
-  category_id: number,
28
-  description: string,
29
-  place: string,
30
-  url: string,
31
-  logo: string | null,
21
+  id: number;
22
+  title: string;
23
+  date_begin: string;
24
+  club: string;
25
+  category_id: number;
26
+  description: string;
27
+  place: string;
28
+  url: string;
29
+  logo: string | null;
32
 };
30
 };
33
 
31
 
34
 // Regex used to check date string validity
32
 // Regex used to check date string validity
41
  * @param dateString The string to check
39
  * @param dateString The string to check
42
  * @return {boolean}
40
  * @return {boolean}
43
  */
41
  */
44
-export function isEventDateStringFormatValid(dateString: ?string): boolean {
42
+export function isEventDateStringFormatValid(dateString?: string): boolean {
45
   return (
43
   return (
46
     dateString !== undefined &&
44
     dateString !== undefined &&
47
     dateString !== null &&
45
     dateString !== null &&
57
  * @return {Date|null} The date object or null if the given string is invalid
55
  * @return {Date|null} The date object or null if the given string is invalid
58
  */
56
  */
59
 export function stringToDate(dateString: string): Date | null {
57
 export function stringToDate(dateString: string): Date | null {
60
-  let date = new Date();
58
+  let date: Date | null = new Date();
61
   if (isEventDateStringFormatValid(dateString)) {
59
   if (isEventDateStringFormatValid(dateString)) {
62
     const stringArray = dateString.split(' ');
60
     const stringArray = dateString.split(' ');
63
     const dateArray = stringArray[0].split('-');
61
     const dateArray = stringArray[0].split('-');
68
       parseInt(dateArray[2], 10),
66
       parseInt(dateArray[2], 10),
69
     );
67
     );
70
     date.setHours(parseInt(timeArray[0], 10), parseInt(timeArray[1], 10), 0, 0);
68
     date.setHours(parseInt(timeArray[0], 10), parseInt(timeArray[1], 10), 0, 0);
71
-  } else date = null;
69
+  } else {
70
+    date = null;
71
+  }
72
 
72
 
73
   return date;
73
   return date;
74
 }
74
 }
111
 export function isEventBefore(event1Date: string, event2Date: string): boolean {
111
 export function isEventBefore(event1Date: string, event2Date: string): boolean {
112
   const date1 = stringToDate(event1Date);
112
   const date1 = stringToDate(event1Date);
113
   const date2 = stringToDate(event2Date);
113
   const date2 = stringToDate(event2Date);
114
-  if (date1 !== null && date2 !== null) return date1 < date2;
114
+  if (date1 !== null && date2 !== null) {
115
+    return date1 < date2;
116
+  }
115
   return false;
117
   return false;
116
 }
118
 }
117
 
119
 
123
  * @return {string|null} Date in format YYYY:MM:DD or null if given string is invalid
125
  * @return {string|null} Date in format YYYY:MM:DD or null if given string is invalid
124
  */
126
  */
125
 export function getDateOnlyString(dateString: string): string | null {
127
 export function getDateOnlyString(dateString: string): string | null {
126
-  if (isEventDateStringFormatValid(dateString)) return dateString.split(' ')[0];
128
+  if (isEventDateStringFormatValid(dateString)) {
129
+    return dateString.split(' ')[0];
130
+  }
127
   return null;
131
   return null;
128
 }
132
 }
129
 
133
 
135
  * @return {string|null} Time in format HH:MM or null if given string is invalid
139
  * @return {string|null} Time in format HH:MM or null if given string is invalid
136
  */
140
  */
137
 export function getTimeOnlyString(dateString: string): string | null {
141
 export function getTimeOnlyString(dateString: string): string | null {
138
-  if (isEventDateStringFormatValid(dateString)) return dateString.split(' ')[1];
142
+  if (isEventDateStringFormatValid(dateString)) {
143
+    return dateString.split(' ')[1];
144
+  }
139
   return null;
145
   return null;
140
 }
146
 }
141
 
147
 
148
  * @param description The text to check
154
  * @param description The text to check
149
  * @return {boolean}
155
  * @return {boolean}
150
  */
156
  */
151
-export function isDescriptionEmpty(description: ?string): boolean {
157
+export function isDescriptionEmpty(description?: string): boolean {
152
   if (description !== undefined && description !== null) {
158
   if (description !== undefined && description !== null) {
153
     return (
159
     return (
154
       description
160
       description
177
 ): {[key: string]: Array<PlanningEventType>} {
183
 ): {[key: string]: Array<PlanningEventType>} {
178
   const end = new Date(Date.now());
184
   const end = new Date(Date.now());
179
   end.setMonth(end.getMonth() + numberOfMonths);
185
   end.setMonth(end.getMonth() + numberOfMonths);
180
-  const daysOfYear = {};
186
+  const daysOfYear: {[key: string]: Array<PlanningEventType>} = {};
181
   for (let d = new Date(Date.now()); d <= end; d.setDate(d.getDate() + 1)) {
187
   for (let d = new Date(Date.now()); d <= end; d.setDate(d.getDate() + 1)) {
182
     const dateString = getDateOnlyString(dateToString(new Date(d), false));
188
     const dateString = getDateOnlyString(dateToString(new Date(d), false));
183
-    if (dateString !== null) daysOfYear[dateString] = [];
189
+    if (dateString !== null) {
190
+      daysOfYear[dateString] = [];
191
+    }
184
   }
192
   }
185
   return daysOfYear;
193
   return daysOfYear;
186
 }
194
 }
197
   eventArray: Array<PlanningEventType>,
205
   eventArray: Array<PlanningEventType>,
198
   event: PlanningEventType,
206
   event: PlanningEventType,
199
 ) {
207
 ) {
200
-  if (eventArray.length === 0) eventArray.push(event);
201
-  else {
208
+  if (eventArray.length === 0) {
209
+    eventArray.push(event);
210
+  } else {
202
     for (let i = 0; i < eventArray.length; i += 1) {
211
     for (let i = 0; i < eventArray.length; i += 1) {
203
       if (isEventBefore(event.date_begin, eventArray[i].date_begin)) {
212
       if (isEventBefore(event.date_begin, eventArray[i].date_begin)) {
204
         eventArray.splice(i, 0, event);
213
         eventArray.splice(i, 0, event);
231
     const dateString = getDateOnlyString(eventList[i].date_begin);
240
     const dateString = getDateOnlyString(eventList[i].date_begin);
232
     if (dateString != null) {
241
     if (dateString != null) {
233
       const eventArray = agendaItems[dateString];
242
       const eventArray = agendaItems[dateString];
234
-      if (eventArray != null) pushEventInOrder(eventArray, eventList[i]);
243
+      if (eventArray != null) {
244
+        pushEventInOrder(eventArray, eventList[i]);
245
+      }
235
     }
246
     }
236
   }
247
   }
237
   return agendaItems;
248
   return agendaItems;

src/utils/Proxiwash.js → src/utils/Proxiwash.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 import type {ProxiwashMachineType} from '../screens/Proxiwash/ProxiwashScreen';
20
 import type {ProxiwashMachineType} from '../screens/Proxiwash/ProxiwashScreen';
23
 
21
 
24
 /**
22
 /**
32
  */
30
  */
33
 export function getMachineEndDate(machine: ProxiwashMachineType): Date | null {
31
 export function getMachineEndDate(machine: ProxiwashMachineType): Date | null {
34
   const array = machine.endTime.split(':');
32
   const array = machine.endTime.split(':');
35
-  let endDate = new Date(Date.now());
33
+  let endDate: Date | null = new Date(Date.now());
36
   endDate.setHours(parseInt(array[0], 10), parseInt(array[1], 10));
34
   endDate.setHours(parseInt(array[0], 10), parseInt(array[1], 10));
37
 
35
 
38
   const limit = new Date(Date.now());
36
   const limit = new Date(Date.now());
39
   if (endDate < limit) {
37
   if (endDate < limit) {
40
     if (limit.getHours() > 12) {
38
     if (limit.getHours() > 12) {
41
       limit.setHours(limit.getHours() - 12);
39
       limit.setHours(limit.getHours() - 12);
42
-      if (endDate < limit) endDate.setDate(endDate.getDate() + 1);
43
-      else endDate = null;
44
-    } else endDate = null;
40
+      if (endDate < limit) {
41
+        endDate.setDate(endDate.getDate() + 1);
42
+      } else {
43
+        endDate = null;
44
+      }
45
+    } else {
46
+      endDate = null;
47
+    }
45
   }
48
   }
46
 
49
 
47
   return endDate;
50
   return endDate;
63
     if (
66
     if (
64
       watchedMachine.number === machine.number &&
67
       watchedMachine.number === machine.number &&
65
       watchedMachine.endTime === machine.endTime
68
       watchedMachine.endTime === machine.endTime
66
-    )
69
+    ) {
67
       watched = true;
70
       watched = true;
71
+    }
68
   });
72
   });
69
   return watched;
73
   return watched;
70
 }
74
 }
82
 ): ProxiwashMachineType | null {
86
 ): ProxiwashMachineType | null {
83
   let machineFound = null;
87
   let machineFound = null;
84
   allMachines.forEach((machine: ProxiwashMachineType) => {
88
   allMachines.forEach((machine: ProxiwashMachineType) => {
85
-    if (machine.number === id) machineFound = machine;
89
+    if (machine.number === id) {
90
+      machineFound = machine;
91
+    }
86
   });
92
   });
87
   return machineFound;
93
   return machineFound;
88
 }
94
 }
100
   machineWatchedList: Array<ProxiwashMachineType>,
106
   machineWatchedList: Array<ProxiwashMachineType>,
101
   allMachines: Array<ProxiwashMachineType>,
107
   allMachines: Array<ProxiwashMachineType>,
102
 ): Array<ProxiwashMachineType> {
108
 ): Array<ProxiwashMachineType> {
103
-  const newList = [];
109
+  const newList: Array<ProxiwashMachineType> = [];
104
   machineWatchedList.forEach((watchedMachine: ProxiwashMachineType) => {
110
   machineWatchedList.forEach((watchedMachine: ProxiwashMachineType) => {
105
     const machine = getMachineOfId(watchedMachine.number, allMachines);
111
     const machine = getMachineOfId(watchedMachine.number, allMachines);
106
     if (
112
     if (

src/utils/Search.js → src/utils/Search.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 /**
20
 /**
23
  * Sanitizes the given string to improve search performance.
21
  * Sanitizes the given string to improve search performance.
24
  *
22
  *
60
 ): boolean {
58
 ): boolean {
61
   let itemFound = false;
59
   let itemFound = false;
62
   categories.forEach((cat: number | null) => {
60
   categories.forEach((cat: number | null) => {
63
-    if (cat != null && filter.indexOf(cat) !== -1) itemFound = true;
61
+    if (cat != null && filter.indexOf(cat) !== -1) {
62
+      itemFound = true;
63
+    }
64
   });
64
   });
65
   return itemFound;
65
   return itemFound;
66
 }
66
 }

src/utils/Utils.js → src/utils/Services.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
-import {Platform, StatusBar} from 'react-native';
23
-import ThemeManager from '../managers/ThemeManager';
20
+/**
21
+ * Gets the given services list without items of the given ids
22
+ *
23
+ * @param idList The ids of items to remove
24
+ * @param sourceList The item list to use as source
25
+ * @returns {[]}
26
+ */
27
+export default function getStrippedServicesList<T extends {key: string}>(
28
+  idList: Array<string>,
29
+  sourceList: Array<T>,
30
+) {
31
+  const newArray: Array<T> = [];
32
+  sourceList.forEach((item: T) => {
33
+    if (!idList.includes(item.key)) {
34
+      newArray.push(item);
35
+    }
36
+  });
37
+  return newArray;
38
+}
24
 
39
 
25
 /**
40
 /**
26
  * Gets a sublist of the given list with items of the given ids only
41
  * Gets a sublist of the given list with items of the given ids only
31
  * @param originalList The original list
46
  * @param originalList The original list
32
  * @returns {[]}
47
  * @returns {[]}
33
  */
48
  */
34
-export function getSublistWithIds<T>(
49
+export function getSublistWithIds<T extends {key: string}>(
35
   idList: Array<string>,
50
   idList: Array<string>,
36
-  originalList: Array<{key: string, ...T}>,
37
-): Array<{key: string, ...T} | null> {
38
-  const subList = [];
51
+  originalList: Array<T>,
52
+) {
53
+  const subList: Array<T | null> = [];
39
   for (let i = 0; i < idList.length; i += 1) {
54
   for (let i = 0; i < idList.length; i += 1) {
40
     subList.push(null);
55
     subList.push(null);
41
   }
56
   }
45
     if (idList.includes(item.key)) {
60
     if (idList.includes(item.key)) {
46
       subList[idList.indexOf(item.key)] = item;
61
       subList[idList.indexOf(item.key)] = item;
47
       itemsAdded += 1;
62
       itemsAdded += 1;
48
-      if (itemsAdded === idList.length) break;
63
+      if (itemsAdded === idList.length) {
64
+        break;
65
+      }
49
     }
66
     }
50
   }
67
   }
51
   return subList;
68
   return subList;
52
 }
69
 }
53
-
54
-/**
55
- * Updates status bar content color if on iOS only,
56
- * as the android status bar is always set to black.
57
- */
58
-export function setupStatusBar() {
59
-  if (ThemeManager.getNightMode()) {
60
-    StatusBar.setBarStyle('light-content', true);
61
-  } else {
62
-    StatusBar.setBarStyle('dark-content', true);
63
-  }
64
-  if (Platform.OS === 'android') {
65
-    StatusBar.setBackgroundColor(
66
-      ThemeManager.getCurrentTheme().colors.surface,
67
-      true,
68
-    );
69
-  }
70
-}

src/utils/URLHandler.js → src/utils/URLHandler.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 import {Linking} from 'react-native';
20
 import {Linking} from 'react-native';
23
 
21
 
24
 export type ParsedUrlDataType = {
22
 export type ParsedUrlDataType = {
25
-  route: string,
26
-  data: {[key: string]: string},
23
+  route: string;
24
+  data: {[key: string]: string};
27
 };
25
 };
28
 
26
 
29
 export type ParsedUrlCallbackType = (parsedData: ParsedUrlDataType) => void;
27
 export type ParsedUrlCallbackType = (parsedData: ParsedUrlDataType) => void;
30
 
28
 
31
 type RawParsedUrlDataType = {
29
 type RawParsedUrlDataType = {
32
-  path: string,
33
-  queryParams: {[key: string]: string},
30
+  path: string;
31
+  queryParams: {[key: string]: string};
34
 };
32
 };
35
 
33
 
36
 /**
34
 /**
69
     let parsedData: RawParsedUrlDataType | null = null;
67
     let parsedData: RawParsedUrlDataType | null = null;
70
     const urlNoScheme = url.replace(URLHandler.SCHEME, '');
68
     const urlNoScheme = url.replace(URLHandler.SCHEME, '');
71
     if (urlNoScheme != null) {
69
     if (urlNoScheme != null) {
72
-      const params = {};
70
+      const params: {[key: string]: string} = {};
73
       const [path, fullParamsString] = urlNoScheme.split('?');
71
       const [path, fullParamsString] = urlNoScheme.split('?');
74
       if (fullParamsString != null) {
72
       if (fullParamsString != null) {
75
         const paramsStringArray = fullParamsString.split('&');
73
         const paramsStringArray = fullParamsString.split('&');
80
           }
78
           }
81
         });
79
         });
82
       }
80
       }
83
-      if (path != null) parsedData = {path, queryParams: params};
81
+      if (path != null) {
82
+        parsedData = {path, queryParams: params};
83
+      }
84
     }
84
     }
85
     return parsedData;
85
     return parsedData;
86
   }
86
   }
99
     if (rawParsedUrlData != null) {
99
     if (rawParsedUrlData != null) {
100
       const {path} = rawParsedUrlData;
100
       const {path} = rawParsedUrlData;
101
       const {queryParams} = rawParsedUrlData;
101
       const {queryParams} = rawParsedUrlData;
102
-      if (URLHandler.isClubInformationLink(path))
102
+      if (URLHandler.isClubInformationLink(path)) {
103
         parsedData = URLHandler.generateClubInformationData(queryParams);
103
         parsedData = URLHandler.generateClubInformationData(queryParams);
104
-      else if (URLHandler.isPlanningInformationLink(path))
104
+      } else if (URLHandler.isPlanningInformationLink(path)) {
105
         parsedData = URLHandler.generatePlanningInformationData(queryParams);
105
         parsedData = URLHandler.generatePlanningInformationData(queryParams);
106
+      }
106
     }
107
     }
107
 
108
 
108
     return parsedData;
109
     return parsedData;
145
    * @returns {null|{route: string, data: {clubId: number}}}
146
    * @returns {null|{route: string, data: {clubId: number}}}
146
    */
147
    */
147
   static generateClubInformationData(params: {
148
   static generateClubInformationData(params: {
148
-    [key: string]: string,
149
+    [key: string]: string;
149
   }): ParsedUrlDataType | null {
150
   }): ParsedUrlDataType | null {
150
     if (params.id != null) {
151
     if (params.id != null) {
151
       const id = parseInt(params.id, 10);
152
       const id = parseInt(params.id, 10);
152
-      if (!Number.isNaN(id))
153
+      if (!Number.isNaN(id)) {
153
         return {
154
         return {
154
           route: URLHandler.CLUB_INFO_ROUTE,
155
           route: URLHandler.CLUB_INFO_ROUTE,
155
           data: {clubId: id.toString()},
156
           data: {clubId: id.toString()},
156
         };
157
         };
158
+      }
157
     }
159
     }
158
     return null;
160
     return null;
159
   }
161
   }
165
    * @returns {null|{route: string, data: {clubId: number}}}
167
    * @returns {null|{route: string, data: {clubId: number}}}
166
    */
168
    */
167
   static generatePlanningInformationData(params: {
169
   static generatePlanningInformationData(params: {
168
-    [key: string]: string,
170
+    [key: string]: string;
169
   }): ParsedUrlDataType | null {
171
   }): ParsedUrlDataType | null {
170
     if (params.id != null) {
172
     if (params.id != null) {
171
       const id = parseInt(params.id, 10);
173
       const id = parseInt(params.id, 10);
201
   onUrl = ({url}: {url: string}) => {
203
   onUrl = ({url}: {url: string}) => {
202
     if (url != null) {
204
     if (url != null) {
203
       const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
205
       const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
204
-      if (data != null) this.onDetectURL(data);
206
+      if (data != null) {
207
+        this.onDetectURL(data);
208
+      }
205
     }
209
     }
206
   };
210
   };
207
 
211
 
210
    *
214
    *
211
    * @param url The url detected
215
    * @param url The url detected
212
    */
216
    */
213
-  onInitialUrl = (url: ?string) => {
217
+  onInitialUrl = (url: string | null) => {
214
     if (url != null) {
218
     if (url != null) {
215
       const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
219
       const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
216
-      if (data != null) this.onInitialURLParsed(data);
220
+      if (data != null) {
221
+        this.onInitialURLParsed(data);
222
+      }
217
     }
223
     }
218
   };
224
   };
219
 }
225
 }

src/utils/Services.js → src/utils/Utils.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
20
+import {Platform, StatusBar} from 'react-native';
21
+import ThemeManager from '../managers/ThemeManager';
21
 
22
 
22
 /**
23
 /**
23
- * Gets the given services list without items of the given ids
24
- *
25
- * @param idList The ids of items to remove
26
- * @param sourceList The item list to use as source
27
- * @returns {[]}
24
+ * Updates status bar content color if on iOS only,
25
+ * as the android status bar is always set to black.
28
  */
26
  */
29
-export default function getStrippedServicesList<T>(
30
-  idList: Array<string>,
31
-  sourceList: Array<{key: string, ...T}>,
32
-): Array<{key: string, ...T}> {
33
-  const newArray = [];
34
-  sourceList.forEach((item: {key: string, ...T}) => {
35
-    if (!idList.includes(item.key)) newArray.push(item);
36
-  });
37
-  return newArray;
27
+export function setupStatusBar() {
28
+  if (ThemeManager.getNightMode()) {
29
+    StatusBar.setBarStyle('light-content', true);
30
+  } else {
31
+    StatusBar.setBarStyle('dark-content', true);
32
+  }
33
+  if (Platform.OS === 'android') {
34
+    StatusBar.setBackgroundColor(
35
+      ThemeManager.getCurrentTheme().colors.surface,
36
+      true,
37
+    );
38
+  }
38
 }
39
 }

src/utils/WebData.js → src/utils/WebData.ts View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 export const ERROR_TYPE = {
20
 export const ERROR_TYPE = {
23
   SUCCESS: 0,
21
   SUCCESS: 0,
24
   BAD_CREDENTIALS: 1,
22
   BAD_CREDENTIALS: 1,
34
 };
32
 };
35
 
33
 
36
 export type ApiDataLoginType = {
34
 export type ApiDataLoginType = {
37
-  token: string,
35
+  token: string;
38
 };
36
 };
39
 
37
 
40
-// eslint-disable-next-line flowtype/no-weak-types
41
 export type ApiGenericDataType = {[key: string]: any};
38
 export type ApiGenericDataType = {[key: string]: any};
42
 
39
 
43
-type ApiResponseType = {
44
-  error: number,
45
-  data: ApiGenericDataType,
40
+type ApiResponseType<T> = {
41
+  error: number;
42
+  data: T;
46
 };
43
 };
47
 
44
 
48
 const API_ENDPOINT = 'https://www.amicale-insat.fr/api/';
45
 const API_ENDPOINT = 'https://www.amicale-insat.fr/api/';
55
  * @param response
52
  * @param response
56
  * @returns {boolean}
53
  * @returns {boolean}
57
  */
54
  */
58
-export function isApiResponseValid(response: ApiResponseType): boolean {
55
+export function isApiResponseValid<T>(response: ApiResponseType<T>): boolean {
59
   return (
56
   return (
60
     response != null &&
57
     response != null &&
61
     response.error != null &&
58
     response.error != null &&
62
-    typeof response.error === 'number' &&
63
     response.data != null &&
59
     response.data != null &&
64
     typeof response.data === 'object'
60
     typeof response.data === 'object'
65
   );
61
   );
76
  * @param params The params to use for this request
72
  * @param params The params to use for this request
77
  * @returns {Promise<ApiGenericDataType>}
73
  * @returns {Promise<ApiGenericDataType>}
78
  */
74
  */
79
-export async function apiRequest(
75
+export async function apiRequest<T>(
80
   path: string,
76
   path: string,
81
   method: string,
77
   method: string,
82
-  params?: {...},
83
-): Promise<ApiGenericDataType> {
78
+  params?: object,
79
+): Promise<T> {
84
   return new Promise(
80
   return new Promise(
85
-    (
86
-      resolve: (data: ApiGenericDataType) => void,
87
-      reject: (error: number) => void,
88
-    ) => {
81
+    (resolve: (data: T) => void, reject: (error: number) => void) => {
89
       let requestParams = {};
82
       let requestParams = {};
90
-      if (params != null) requestParams = {...params};
83
+      if (params != null) {
84
+        requestParams = {...params};
85
+      }
91
       fetch(API_ENDPOINT + path, {
86
       fetch(API_ENDPOINT + path, {
92
         method,
87
         method,
93
         headers: new Headers({
88
         headers: new Headers({
96
         }),
91
         }),
97
         body: JSON.stringify(requestParams),
92
         body: JSON.stringify(requestParams),
98
       })
93
       })
99
-        .then(async (response: Response): Promise<ApiResponseType> =>
100
-          response.json(),
94
+        .then(
95
+          async (response: Response): Promise<ApiResponseType<T>> =>
96
+            response.json(),
101
         )
97
         )
102
-        .then((response: ApiResponseType) => {
98
+        .then((response: ApiResponseType<T>) => {
103
           if (isApiResponseValid(response)) {
99
           if (isApiResponseValid(response)) {
104
-            if (response.error === ERROR_TYPE.SUCCESS) resolve(response.data);
105
-            else reject(response.error);
106
-          } else reject(ERROR_TYPE.SERVER_ERROR);
100
+            if (response.error === ERROR_TYPE.SUCCESS) {
101
+              resolve(response.data);
102
+            } else {
103
+              reject(response.error);
104
+            }
105
+          } else {
106
+            reject(ERROR_TYPE.SERVER_ERROR);
107
+          }
107
         })
108
         })
108
         .catch((): void => reject(ERROR_TYPE.CONNECTION_ERROR));
109
         .catch((): void => reject(ERROR_TYPE.CONNECTION_ERROR));
109
     },
110
     },
121
  * @param url The urls to fetch data from
122
  * @param url The urls to fetch data from
122
  * @return Promise<any>
123
  * @return Promise<any>
123
  */
124
  */
124
-// eslint-disable-next-line flowtype/no-weak-types
125
 export async function readData(url: string): Promise<any> {
125
 export async function readData(url: string): Promise<any> {
126
-  // eslint-disable-next-line flowtype/no-weak-types
127
   return new Promise((resolve: (response: any) => void, reject: () => void) => {
126
   return new Promise((resolve: (response: any) => void, reject: () => void) => {
128
     fetch(url)
127
     fetch(url)
129
-      // eslint-disable-next-line flowtype/no-weak-types
130
       .then(async (response: Response): Promise<any> => response.json())
128
       .then(async (response: Response): Promise<any> => response.json())
131
-      // eslint-disable-next-line flowtype/no-weak-types
132
       .then((data: any): void => resolve(data))
129
       .then((data: any): void => resolve(data))
133
       .catch((): void => reject());
130
       .catch((): void => reject());
134
   });
131
   });

src/utils/withCollapsible.js → src/utils/withCollapsible.tsx View File

17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
  */
18
  */
19
 
19
 
20
-// @flow
21
-
22
 import * as React from 'react';
20
 import * as React from 'react';
23
 import {useCollapsibleStack} from 'react-navigation-collapsible';
21
 import {useCollapsibleStack} from 'react-navigation-collapsible';
24
 
22
 
35
  * @param Component The component to use Collapsible with
33
  * @param Component The component to use Collapsible with
36
  * @returns {React.ComponentType<any>}
34
  * @returns {React.ComponentType<any>}
37
  */
35
  */
38
-export default function withCollapsible(
39
-  // eslint-disable-next-line flowtype/no-weak-types
40
-  Component: React.ComponentType<any>,
41
-  // eslint-disable-next-line flowtype/no-weak-types
42
-): React$AbstractComponent<any, any> {
43
-  // eslint-disable-next-line flowtype/no-weak-types
44
-  return React.forwardRef((props: any, ref: any): React.Node => {
36
+export default function withCollapsible(Component: React.ComponentType<any>) {
37
+  return React.forwardRef((props: any, ref: any) => {
45
     return (
38
     return (
46
       <Component
39
       <Component
47
         collapsibleStack={useCollapsibleStack()}
40
         collapsibleStack={useCollapsibleStack()}
48
         ref={ref}
41
         ref={ref}
49
-        // eslint-disable-next-line react/jsx-props-no-spreading
50
         {...props}
42
         {...props}
51
       />
43
       />
52
     );
44
     );

Loading…
Cancel
Save