Browse Source

Update remaining Amicale screens to use TypeScript

Arnaud Vergnet 3 years ago
parent
commit
d70f22bdae

src/screens/Amicale/AmicaleContactScreen.js → src/screens/Amicale/AmicaleContactScreen.tsx View File

@@ -17,24 +17,18 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import * as React from 'react';
23 21
 import {FlatList, Image, Linking, View} from 'react-native';
24
-import {Card, List, Text, withTheme, Avatar} from 'react-native-paper';
22
+import {Avatar, Card, List, Text} from 'react-native-paper';
25 23
 import i18n from 'i18n-js';
26
-import type {MaterialCommunityIconsGlyphs} from 'react-native-vector-icons/MaterialCommunityIcons';
27 24
 import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatList';
28
-import AMICALE_LOGO from '../../../assets/amicale.png';
29
-import type {
30
-  CardTitleIconPropsType,
31
-  ListIconPropsType,
32
-} from '../../constants/PaperStyles';
25
+
26
+const AMICALE_LOGO = require('../../../assets/amicale.png');
33 27
 
34 28
 type DatasetItemType = {
35
-  name: string,
36
-  email: string,
37
-  icon: MaterialCommunityIconsGlyphs,
29
+  name: string;
30
+  email: string;
31
+  icon: string;
38 32
 };
39 33
 
40 34
 /**
@@ -45,7 +39,7 @@ class AmicaleContactScreen extends React.Component<null> {
45 39
   CONTACT_DATASET: Array<DatasetItemType>;
46 40
 
47 41
   constructor() {
48
-    super();
42
+    super(null);
49 43
     this.CONTACT_DATASET = [
50 44
       {
51 45
         name: i18n.t('screens.amicaleAbout.roles.interSchools'),
@@ -97,7 +91,13 @@ class AmicaleContactScreen extends React.Component<null> {
97 91
 
98 92
   keyExtractor = (item: DatasetItemType): string => item.email;
99 93
 
100
-  getChevronIcon = (iconProps: ListIconPropsType): React.Node => (
94
+  getChevronIcon = (iconProps: {
95
+    color: string;
96
+    style?: {
97
+      marginRight: number;
98
+      marginVertical?: number;
99
+    };
100
+  }) => (
101 101
     <List.Icon
102 102
       color={iconProps.color}
103 103
       style={iconProps.style}
@@ -105,7 +105,7 @@ class AmicaleContactScreen extends React.Component<null> {
105 105
     />
106 106
   );
107 107
 
108
-  getRenderItem = ({item}: {item: DatasetItemType}): React.Node => {
108
+  getRenderItem = ({item}: {item: DatasetItemType}) => {
109 109
     const onPress = () => {
110 110
       Linking.openURL(`mailto:${item.email}`);
111 111
     };
@@ -113,7 +113,7 @@ class AmicaleContactScreen extends React.Component<null> {
113 113
       <List.Item
114 114
         title={item.name}
115 115
         description={item.email}
116
-        left={(iconProps: ListIconPropsType): React.Node => (
116
+        left={(iconProps) => (
117 117
           <List.Icon
118 118
             color={iconProps.color}
119 119
             style={iconProps.style}
@@ -126,7 +126,7 @@ class AmicaleContactScreen extends React.Component<null> {
126 126
     );
127 127
   };
128 128
 
129
-  getScreen = (): React.Node => {
129
+  getScreen = () => {
130 130
     return (
131 131
       <View>
132 132
         <View
@@ -148,7 +148,7 @@ class AmicaleContactScreen extends React.Component<null> {
148 148
           <Card.Title
149 149
             title={i18n.t('screens.amicaleAbout.title')}
150 150
             subtitle={i18n.t('screens.amicaleAbout.subtitle')}
151
-            left={(iconProps: CardTitleIconPropsType): React.Node => (
151
+            left={(iconProps) => (
152 152
               <Avatar.Icon size={iconProps.size} icon="information" />
153 153
             )}
154 154
           />
@@ -165,7 +165,7 @@ class AmicaleContactScreen extends React.Component<null> {
165 165
     );
166 166
   };
167 167
 
168
-  render(): React.Node {
168
+  render() {
169 169
     return (
170 170
       <CollapsibleFlatList
171 171
         data={[{key: '1'}]}
@@ -176,4 +176,4 @@ class AmicaleContactScreen extends React.Component<null> {
176 176
   }
177 177
 }
178 178
 
179
-export default withTheme(AmicaleContactScreen);
179
+export default AmicaleContactScreen;

src/screens/Amicale/LoginScreen.js → src/screens/Amicale/LoginScreen.tsx View File

@@ -17,8 +17,6 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import * as React from 'react';
23 21
 import {Image, KeyboardAvoidingView, StyleSheet, View} from 'react-native';
24 22
 import {
@@ -29,32 +27,33 @@ import {
29 27
   withTheme,
30 28
 } from 'react-native-paper';
31 29
 import i18n from 'i18n-js';
32
-import {StackNavigationProp} from '@react-navigation/stack';
30
+import {StackNavigationProp, StackScreenProps} from '@react-navigation/stack';
33 31
 import LinearGradient from 'react-native-linear-gradient';
34 32
 import ConnectionManager from '../../managers/ConnectionManager';
35 33
 import ErrorDialog from '../../components/Dialogs/ErrorDialog';
36
-import type {CustomThemeType} from '../../managers/ThemeManager';
37 34
 import AsyncStorageManager from '../../managers/AsyncStorageManager';
38 35
 import AvailableWebsites from '../../constants/AvailableWebsites';
39 36
 import {MASCOT_STYLE} from '../../components/Mascot/Mascot';
40 37
 import MascotPopup from '../../components/Mascot/MascotPopup';
41 38
 import CollapsibleScrollView from '../../components/Collapsible/CollapsibleScrollView';
39
+import {MainStackParamsList} from '../../navigation/MainNavigator';
40
+
41
+type LoginScreenNavigationProp = StackScreenProps<MainStackParamsList, 'login'>;
42 42
 
43
-type PropsType = {
44
-  navigation: StackNavigationProp,
45
-  route: {params: {nextScreen: string}},
46
-  theme: CustomThemeType,
43
+type Props = LoginScreenNavigationProp & {
44
+  navigation: StackNavigationProp<any>;
45
+  theme: ReactNativePaper.Theme;
47 46
 };
48 47
 
49 48
 type StateType = {
50
-  email: string,
51
-  password: string,
52
-  isEmailValidated: boolean,
53
-  isPasswordValidated: boolean,
54
-  loading: boolean,
55
-  dialogVisible: boolean,
56
-  dialogError: number,
57
-  mascotDialogVisible: boolean,
49
+  email: string;
50
+  password: string;
51
+  isEmailValidated: boolean;
52
+  isPasswordValidated: boolean;
53
+  loading: boolean;
54
+  dialogVisible: boolean;
55
+  dialogError: number;
56
+  mascotDialogVisible: boolean;
58 57
 };
59 58
 
60 59
 const ICON_AMICALE = require('../../../assets/amicale.png');
@@ -82,17 +81,21 @@ const styles = StyleSheet.create({
82 81
   },
83 82
 });
84 83
 
85
-class LoginScreen extends React.Component<PropsType, StateType> {
84
+class LoginScreen extends React.Component<Props, StateType> {
86 85
   onEmailChange: (value: string) => void;
87 86
 
88 87
   onPasswordChange: (value: string) => void;
89 88
 
90
-  passwordInputRef: {current: null | TextInput};
89
+  passwordInputRef: {
90
+    // @ts-ignore
91
+    current: null | TextInput;
92
+  };
91 93
 
92 94
   nextScreen: string | null;
93 95
 
94
-  constructor(props: PropsType) {
96
+  constructor(props: Props) {
95 97
     super(props);
98
+    this.nextScreen = null;
96 99
     this.passwordInputRef = React.createRef();
97 100
     this.onEmailChange = (value: string) => {
98 101
       this.onInputChange(true, value);
@@ -158,8 +161,9 @@ class LoginScreen extends React.Component<PropsType, StateType> {
158 161
    * @returns {*}
159 162
    */
160 163
   onEmailSubmit = () => {
161
-    if (this.passwordInputRef.current != null)
164
+    if (this.passwordInputRef.current != null) {
162 165
       this.passwordInputRef.current.focus();
166
+    }
163 167
   };
164 168
 
165 169
   /**
@@ -188,7 +192,7 @@ class LoginScreen extends React.Component<PropsType, StateType> {
188 192
    *
189 193
    * @returns {*}
190 194
    */
191
-  getFormInput(): React.Node {
195
+  getFormInput() {
192 196
     const {email, password} = this.state;
193 197
     return (
194 198
       <View>
@@ -239,7 +243,7 @@ class LoginScreen extends React.Component<PropsType, StateType> {
239 243
    * Gets the card containing the input form
240 244
    * @returns {*}
241 245
    */
242
-  getMainCard(): React.Node {
246
+  getMainCard() {
243 247
     const {props, state} = this;
244 248
     return (
245 249
       <View style={styles.card}>
@@ -248,7 +252,7 @@ class LoginScreen extends React.Component<PropsType, StateType> {
248 252
           titleStyle={{color: '#fff'}}
249 253
           subtitle={i18n.t('screens.login.subtitle')}
250 254
           subtitleStyle={{color: '#fff'}}
251
-          left={({size}: {size: number}): React.Node => (
255
+          left={({size}) => (
252 256
             <Image
253 257
               source={ICON_AMICALE}
254 258
               style={{
@@ -349,20 +353,18 @@ class LoginScreen extends React.Component<PropsType, StateType> {
349 353
       AsyncStorageManager.PREFERENCES.homeShowMascot.key,
350 354
       false,
351 355
     );
352
-    if (this.nextScreen == null) navigation.goBack();
353
-    else navigation.replace(this.nextScreen);
356
+    if (this.nextScreen == null) {
357
+      navigation.goBack();
358
+    } else {
359
+      navigation.replace(this.nextScreen);
360
+    }
354 361
   };
355 362
 
356 363
   /**
357 364
    * Saves the screen to navigate to after a successful login if one was provided in navigation parameters
358 365
    */
359 366
   handleNavigationParams() {
360
-    const {route} = this.props;
361
-    if (route.params != null) {
362
-      if (route.params.nextScreen != null)
363
-        this.nextScreen = route.params.nextScreen;
364
-      else this.nextScreen = null;
365
-    }
367
+    this.nextScreen = this.props.route.params.nextScreen;
366 368
   }
367 369
 
368 370
   /**
@@ -417,7 +419,7 @@ class LoginScreen extends React.Component<PropsType, StateType> {
417 419
     return this.isEmailValid() && this.isPasswordValid() && !loading;
418 420
   }
419 421
 
420
-  render(): React.Node {
422
+  render() {
421 423
     const {mascotDialogVisible, dialogVisible, dialogError} = this.state;
422 424
     return (
423 425
       <LinearGradient
@@ -441,7 +443,6 @@ class LoginScreen extends React.Component<PropsType, StateType> {
441 443
               message={i18n.t('screens.login.mascotDialog.message')}
442 444
               icon="help"
443 445
               buttons={{
444
-                action: null,
445 446
                 cancel: {
446 447
                   message: i18n.t('screens.login.mascotDialog.button'),
447 448
                   icon: 'check',

src/screens/Amicale/ProfileScreen.js → src/screens/Amicale/ProfileScreen.tsx View File

@@ -17,8 +17,6 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import * as React from 'react';
23 21
 import {FlatList, StyleSheet, View} from 'react-native';
24 22
 import {
@@ -38,42 +36,37 @@ import MaterialHeaderButtons, {
38 36
   Item,
39 37
 } from '../../components/Overrides/CustomHeaderButton';
40 38
 import CardList from '../../components/Lists/CardList/CardList';
41
-import type {CustomThemeType} from '../../managers/ThemeManager';
42 39
 import AvailableWebsites from '../../constants/AvailableWebsites';
43 40
 import Mascot, {MASCOT_STYLE} from '../../components/Mascot/Mascot';
44 41
 import ServicesManager, {SERVICES_KEY} from '../../managers/ServicesManager';
45 42
 import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatList';
46 43
 import type {ServiceItemType} from '../../managers/ServicesManager';
47
-import type {
48
-  CardTitleIconPropsType,
49
-  ListIconPropsType,
50
-} from '../../constants/PaperStyles';
51 44
 
52 45
 type PropsType = {
53
-  navigation: StackNavigationProp,
54
-  theme: CustomThemeType,
46
+  navigation: StackNavigationProp<any>;
47
+  theme: ReactNativePaper.Theme;
55 48
 };
56 49
 
57 50
 type StateType = {
58
-  dialogVisible: boolean,
51
+  dialogVisible: boolean;
59 52
 };
60 53
 
61 54
 type ClubType = {
62
-  id: number,
63
-  name: string,
64
-  is_manager: boolean,
55
+  id: number;
56
+  name: string;
57
+  is_manager: boolean;
65 58
 };
66 59
 
67 60
 type ProfileDataType = {
68
-  first_name: string,
69
-  last_name: string,
70
-  email: string,
71
-  birthday: string,
72
-  phone: string,
73
-  branch: string,
74
-  link: string,
75
-  validity: boolean,
76
-  clubs: Array<ClubType>,
61
+  first_name: string;
62
+  last_name: string;
63
+  email: string;
64
+  birthday: string;
65
+  phone: string;
66
+  branch: string;
67
+  link: string;
68
+  validity: boolean;
69
+  clubs: Array<ClubType>;
77 70
 };
78 71
 
79 72
 const styles = StyleSheet.create({
@@ -89,7 +82,7 @@ const styles = StyleSheet.create({
89 82
 });
90 83
 
91 84
 class ProfileScreen extends React.Component<PropsType, StateType> {
92
-  data: ProfileDataType;
85
+  data: ProfileDataType | null;
93 86
 
94 87
   flatListData: Array<{id: string}>;
95 88
 
@@ -97,6 +90,7 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
97 90
 
98 91
   constructor(props: PropsType) {
99 92
     super(props);
93
+    this.data = null;
100 94
     this.flatListData = [{id: '0'}, {id: '1'}, {id: '2'}, {id: '3'}];
101 95
     const services = new ServicesManager(props.navigation);
102 96
     this.amicaleDataset = services.getAmicaleServices([SERVICES_KEY.PROFILE]);
@@ -117,7 +111,7 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
117 111
    *
118 112
    * @returns {*}
119 113
    */
120
-  getHeaderButton = (): React.Node => (
114
+  getHeaderButton = () => (
121 115
     <MaterialHeaderButtons>
122 116
       <Item
123 117
         title="logout"
@@ -133,12 +127,9 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
133 127
    * @param data The data fetched from the server
134 128
    * @returns {*}
135 129
    */
136
-  getScreen = (data: Array<ProfileDataType | null>): React.Node => {
130
+  getScreen = (data: Array<ProfileDataType | null>) => {
137 131
     const {dialogVisible} = this.state;
138
-    const {navigation} = this.props;
139
-    // eslint-disable-next-line prefer-destructuring
140
-    if (data[0] != null) this.data = data[0];
141
-
132
+    this.data = data[0];
142 133
     return (
143 134
       <View style={{flex: 1}}>
144 135
         <CollapsibleFlatList
@@ -146,7 +137,6 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
146 137
           data={this.flatListData}
147 138
         />
148 139
         <LogoutDialog
149
-          navigation={navigation}
150 140
           visible={dialogVisible}
151 141
           onDismiss={this.hideDisconnectDialog}
152 142
         />
@@ -154,7 +144,7 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
154 144
     );
155 145
   };
156 146
 
157
-  getRenderItem = ({item}: {item: {id: string}}): React.Node => {
147
+  getRenderItem = ({item}: {item: {id: string}}) => {
158 148
     switch (item.id) {
159 149
       case '0':
160 150
         return this.getWelcomeCard();
@@ -172,7 +162,7 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
172 162
    *
173 163
    * @returns {*}
174 164
    */
175
-  getServicesList(): React.Node {
165
+  getServicesList() {
176 166
     return <CardList dataset={this.amicaleDataset} isHorizontal />;
177 167
   }
178 168
 
@@ -181,15 +171,15 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
181 171
    *
182 172
    * @returns {*}
183 173
    */
184
-  getWelcomeCard(): React.Node {
174
+  getWelcomeCard() {
185 175
     const {navigation} = this.props;
186 176
     return (
187 177
       <Card style={styles.card}>
188 178
         <Card.Title
189 179
           title={i18n.t('screens.profile.welcomeTitle', {
190
-            name: this.data.first_name,
180
+            name: this.data?.first_name,
191 181
           })}
192
-          left={(): React.Node => (
182
+          left={() => (
193 183
             <Mascot
194 184
               style={{
195 185
                 width: 60,
@@ -233,8 +223,8 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
233 223
    * @param field The field to get the value from
234 224
    * @return {*}
235 225
    */
236
-  static getFieldValue(field: ?string): string {
237
-    return field != null ? field : i18n.t('screens.profile.noData');
226
+  static getFieldValue(field?: string): string {
227
+    return field ? field : i18n.t('screens.profile.noData');
238 228
   }
239 229
 
240 230
   /**
@@ -244,7 +234,7 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
244 234
    * @param icon The icon to use
245 235
    * @return {*}
246 236
    */
247
-  getPersonalListItem(field: ?string, icon: string): React.Node {
237
+  getPersonalListItem(field: string | undefined, icon: string) {
248 238
     const {theme} = this.props;
249 239
     const title = field != null ? ProfileScreen.getFieldValue(field) : ':(';
250 240
     const subtitle = field != null ? '' : ProfileScreen.getFieldValue(field);
@@ -252,7 +242,7 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
252 242
       <List.Item
253 243
         title={title}
254 244
         description={subtitle}
255
-        left={(props: ListIconPropsType): React.Node => (
245
+        left={(props) => (
256 246
           <List.Icon
257 247
             style={props.style}
258 248
             icon={icon}
@@ -268,14 +258,14 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
268 258
    *
269 259
    * @return {*}
270 260
    */
271
-  getPersonalCard(): React.Node {
261
+  getPersonalCard() {
272 262
     const {theme, navigation} = this.props;
273 263
     return (
274 264
       <Card style={styles.card}>
275 265
         <Card.Title
276
-          title={`${this.data.first_name} ${this.data.last_name}`}
277
-          subtitle={this.data.email}
278
-          left={(iconProps: CardTitleIconPropsType): React.Node => (
266
+          title={`${this.data?.first_name} ${this.data?.last_name}`}
267
+          subtitle={this.data?.email}
268
+          left={(iconProps) => (
279 269
             <Avatar.Icon
280 270
               size={iconProps.size}
281 271
               icon="account"
@@ -290,10 +280,10 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
290 280
             <List.Subheader>
291 281
               {i18n.t('screens.profile.personalInformation')}
292 282
             </List.Subheader>
293
-            {this.getPersonalListItem(this.data.birthday, 'cake-variant')}
294
-            {this.getPersonalListItem(this.data.phone, 'phone')}
295
-            {this.getPersonalListItem(this.data.email, 'email')}
296
-            {this.getPersonalListItem(this.data.branch, 'school')}
283
+            {this.getPersonalListItem(this.data?.birthday, 'cake-variant')}
284
+            {this.getPersonalListItem(this.data?.phone, 'phone')}
285
+            {this.getPersonalListItem(this.data?.email, 'email')}
286
+            {this.getPersonalListItem(this.data?.branch, 'school')}
297 287
           </List.Section>
298 288
           <Divider />
299 289
           <Card.Actions>
@@ -303,7 +293,7 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
303 293
               onPress={() => {
304 294
                 navigation.navigate('website', {
305 295
                   host: AvailableWebsites.websites.AMICALE,
306
-                  path: this.data.link,
296
+                  path: this.data?.link,
307 297
                   title: i18n.t('screens.websites.amicale'),
308 298
                 });
309 299
               }}
@@ -321,14 +311,14 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
321 311
    *
322 312
    * @return {*}
323 313
    */
324
-  getClubCard(): React.Node {
314
+  getClubCard() {
325 315
     const {theme} = this.props;
326 316
     return (
327 317
       <Card style={styles.card}>
328 318
         <Card.Title
329 319
           title={i18n.t('screens.profile.clubs')}
330 320
           subtitle={i18n.t('screens.profile.clubsSubtitle')}
331
-          left={(iconProps: CardTitleIconPropsType): React.Node => (
321
+          left={(iconProps) => (
332 322
             <Avatar.Icon
333 323
               size={iconProps.size}
334 324
               icon="account-group"
@@ -339,7 +329,7 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
339 329
         />
340 330
         <Card.Content>
341 331
           <Divider />
342
-          {this.getClubList(this.data.clubs)}
332
+          {this.getClubList(this.data?.clubs)}
343 333
         </Card.Content>
344 334
       </Card>
345 335
     );
@@ -350,14 +340,14 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
350 340
    *
351 341
    * @return {*}
352 342
    */
353
-  getMembershipCar(): React.Node {
343
+  getMembershipCar() {
354 344
     const {theme} = this.props;
355 345
     return (
356 346
       <Card style={styles.card}>
357 347
         <Card.Title
358 348
           title={i18n.t('screens.profile.membership')}
359 349
           subtitle={i18n.t('screens.profile.membershipSubtitle')}
360
-          left={(iconProps: CardTitleIconPropsType): React.Node => (
350
+          left={(iconProps) => (
361 351
             <Avatar.Icon
362 352
               size={iconProps.size}
363 353
               icon="credit-card"
@@ -368,7 +358,7 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
368 358
         />
369 359
         <Card.Content>
370 360
           <List.Section>
371
-            {this.getMembershipItem(this.data.validity)}
361
+            {this.getMembershipItem(this.data?.validity === true)}
372 362
           </List.Section>
373 363
         </Card.Content>
374 364
       </Card>
@@ -380,7 +370,7 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
380 370
    *
381 371
    * @return {*}
382 372
    */
383
-  getMembershipItem(state: boolean): React.Node {
373
+  getMembershipItem(state: boolean) {
384 374
     const {theme} = this.props;
385 375
     return (
386 376
       <List.Item
@@ -389,7 +379,7 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
389 379
             ? i18n.t('screens.profile.membershipPayed')
390 380
             : i18n.t('screens.profile.membershipNotPayed')
391 381
         }
392
-        left={(props: ListIconPropsType): React.Node => (
382
+        left={(props) => (
393 383
           <List.Icon
394 384
             style={props.style}
395 385
             color={state ? theme.colors.success : theme.colors.danger}
@@ -406,18 +396,25 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
406 396
    * @param item The club to render
407 397
    * @return {*}
408 398
    */
409
-  getClubListItem = ({item}: {item: ClubType}): React.Node => {
399
+  getClubListItem = ({item}: {item: ClubType}) => {
410 400
     const {theme} = this.props;
411 401
     const onPress = () => {
412 402
       this.openClubDetailsScreen(item.id);
413 403
     };
414 404
     let description = i18n.t('screens.profile.isMember');
415
-    let icon = (props: ListIconPropsType): React.Node => (
405
+    let icon = (props: {
406
+      color: string;
407
+      style: {
408
+        marginLeft: number;
409
+        marginRight: number;
410
+        marginVertical?: number;
411
+      };
412
+    }) => (
416 413
       <List.Icon color={props.color} style={props.style} icon="chevron-right" />
417 414
     );
418 415
     if (item.is_manager) {
419 416
       description = i18n.t('screens.profile.isManager');
420
-      icon = (props: ListIconPropsType): React.Node => (
417
+      icon = (props) => (
421 418
         <List.Icon
422 419
           style={props.style}
423 420
           icon="star"
@@ -441,7 +438,11 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
441 438
    * @param list The club list
442 439
    * @return {*}
443 440
    */
444
-  getClubList(list: Array<ClubType>): React.Node {
441
+  getClubList(list: Array<ClubType> | undefined) {
442
+    if (!list) {
443
+      return null;
444
+    }
445
+
445 446
     list.sort(this.sortClubList);
446 447
     return (
447 448
       <FlatList
@@ -473,7 +474,7 @@ class ProfileScreen extends React.Component<PropsType, StateType> {
473 474
     navigation.navigate('club-information', {clubId: id});
474 475
   }
475 476
 
476
-  render(): React.Node {
477
+  render() {
477 478
     const {navigation} = this.props;
478 479
     return (
479 480
       <AuthenticatedScreen

Loading…
Cancel
Save