Browse Source

Redirect to login screen if not logged in

Arnaud Vergnet 6 months ago
parent
commit
c500ae05e6

+ 1
- 1
src/components/Amicale/Profile/ProfileWelcomeCard.tsx View File

@@ -51,7 +51,7 @@ function ProfileWelcomeCard(props: Props) {
51 51
         <Divider />
52 52
         <Paragraph>{i18n.t('screens.profile.welcomeDescription')}</Paragraph>
53 53
         <CardList
54
-          dataset={getAmicaleServices(navigation.navigate, [
54
+          dataset={getAmicaleServices(navigation.navigate, true, [
55 55
             SERVICES_KEY.PROFILE,
56 56
           ])}
57 57
           isHorizontal={true}

+ 3
- 1
src/context/preferencesContext.tsx View File

@@ -25,6 +25,7 @@ import {
25 25
   getSpecialServices,
26 26
   getStudentServices,
27 27
 } from '../utils/Services';
28
+import { useLoginState } from './loginContext';
28 29
 
29 30
 const colorScheme = Appearance.getColorScheme();
30 31
 
@@ -135,6 +136,7 @@ export function useDarkTheme() {
135 136
 export function useCurrentDashboard() {
136 137
   const { preferences, updatePreferences } = usePreferences();
137 138
   const navigation = useNavigation();
139
+  const isLoggedIn = useLoginState();
138 140
   const dashboardIdList = getPreferenceObject(
139 141
     GeneralPreferenceKeys.dashboardItems,
140 142
     preferences
@@ -145,7 +147,7 @@ export function useCurrentDashboard() {
145 147
   };
146 148
 
147 149
   const allDatasets = [
148
-    ...getAmicaleServices(navigation.navigate),
150
+    ...getAmicaleServices(navigation.navigate, isLoggedIn),
149 151
     ...getStudentServices(navigation.navigate),
150 152
     ...getINSAServices(navigation.navigate),
151 153
     ...getSpecialServices(navigation.navigate),

+ 62
- 50
src/navigation/MainNavigator.tsx View File

@@ -52,6 +52,7 @@ import {
52 52
   GeneralPreferenceKeys,
53 53
 } from '../utils/asyncStorage';
54 54
 import IntroScreen from '../screens/Intro/IntroScreen';
55
+import { useLoginState } from '../context/loginContext';
55 56
 
56 57
 export enum MainRoutes {
57 58
   Main = 'main',
@@ -118,6 +119,62 @@ function getIntroScreens() {
118 119
   );
119 120
 }
120 121
 
122
+function getAmicaleScreens() {
123
+  return (
124
+    <>
125
+      <MainStack.Screen
126
+        name={MainRoutes.Profile}
127
+        component={ProfileScreen}
128
+        options={{
129
+          title: i18n.t('screens.profile.title'),
130
+        }}
131
+      />
132
+      <MainStack.Screen
133
+        name={MainRoutes.ClubList}
134
+        component={ClubListScreen}
135
+        options={{
136
+          title: i18n.t('screens.clubs.title'),
137
+        }}
138
+      />
139
+      <MainStack.Screen
140
+        name={MainRoutes.ClubInformation}
141
+        component={ClubDisplayScreen}
142
+        options={{
143
+          title: i18n.t('screens.clubs.details'),
144
+        }}
145
+      />
146
+      <MainStack.Screen
147
+        name={MainRoutes.ClubAbout}
148
+        component={ClubAboutScreen}
149
+        options={{
150
+          title: i18n.t('screens.clubs.title'),
151
+        }}
152
+      />
153
+      <MainStack.Screen
154
+        name={MainRoutes.EquipmentList}
155
+        component={EquipmentScreen}
156
+        options={{
157
+          title: i18n.t('screens.equipment.title'),
158
+        }}
159
+      />
160
+      <MainStack.Screen
161
+        name={MainRoutes.EquipmentRent}
162
+        component={EquipmentLendScreen}
163
+        options={{
164
+          title: i18n.t('screens.equipment.book'),
165
+        }}
166
+      />
167
+      <MainStack.Screen
168
+        name={MainRoutes.EquipmentConfirm}
169
+        component={EquipmentConfirmScreen}
170
+        options={{
171
+          title: i18n.t('screens.equipment.confirm'),
172
+        }}
173
+      />
174
+    </>
175
+  );
176
+}
177
+
121 178
 function getRegularScreens(createTabNavigator: () => React.ReactElement) {
122 179
   return (
123 180
     <>
@@ -234,55 +291,6 @@ function getRegularScreens(createTabNavigator: () => React.ReactElement) {
234 291
         }}
235 292
       />
236 293
       <MainStack.Screen
237
-        name={MainRoutes.Profile}
238
-        component={ProfileScreen}
239
-        options={{
240
-          title: i18n.t('screens.profile.title'),
241
-        }}
242
-      />
243
-      <MainStack.Screen
244
-        name={MainRoutes.ClubList}
245
-        component={ClubListScreen}
246
-        options={{
247
-          title: i18n.t('screens.clubs.title'),
248
-        }}
249
-      />
250
-      <MainStack.Screen
251
-        name={MainRoutes.ClubInformation}
252
-        component={ClubDisplayScreen}
253
-        options={{
254
-          title: i18n.t('screens.clubs.details'),
255
-        }}
256
-      />
257
-      <MainStack.Screen
258
-        name={MainRoutes.ClubAbout}
259
-        component={ClubAboutScreen}
260
-        options={{
261
-          title: i18n.t('screens.clubs.title'),
262
-        }}
263
-      />
264
-      <MainStack.Screen
265
-        name={MainRoutes.EquipmentList}
266
-        component={EquipmentScreen}
267
-        options={{
268
-          title: i18n.t('screens.equipment.title'),
269
-        }}
270
-      />
271
-      <MainStack.Screen
272
-        name={MainRoutes.EquipmentRent}
273
-        component={EquipmentLendScreen}
274
-        options={{
275
-          title: i18n.t('screens.equipment.book'),
276
-        }}
277
-      />
278
-      <MainStack.Screen
279
-        name={MainRoutes.EquipmentConfirm}
280
-        component={EquipmentConfirmScreen}
281
-        options={{
282
-          title: i18n.t('screens.equipment.confirm'),
283
-        }}
284
-      />
285
-      <MainStack.Screen
286 294
         name={MainRoutes.Vote}
287 295
         component={VoteScreen}
288 296
         options={{
@@ -302,15 +310,17 @@ function getRegularScreens(createTabNavigator: () => React.ReactElement) {
302 310
 
303 311
 function MainStackComponent(props: {
304 312
   showIntro: boolean;
313
+  isloggedIn: boolean;
305 314
   createTabNavigator: () => React.ReactElement;
306 315
 }) {
307
-  const { showIntro, createTabNavigator } = props;
316
+  const { showIntro, isloggedIn, createTabNavigator } = props;
308 317
   return (
309 318
     <MainStack.Navigator
310 319
       initialRouteName={showIntro ? MainRoutes.Intro : MainRoutes.Main}
311 320
       headerMode={'screen'}
312 321
     >
313 322
       {showIntro ? getIntroScreens() : getRegularScreens(createTabNavigator)}
323
+      {isloggedIn ? getAmicaleScreens() : null}
314 324
     </MainStack.Navigator>
315 325
   );
316 326
 }
@@ -322,6 +332,7 @@ type PropsType = {
322 332
 
323 333
 function MainNavigator(props: PropsType) {
324 334
   const { preferences } = usePreferences();
335
+  const isloggedIn = useLoginState();
325 336
   const showIntro = getPreferenceBool(
326 337
     GeneralPreferenceKeys.showIntro,
327 338
     preferences
@@ -330,6 +341,7 @@ function MainNavigator(props: PropsType) {
330 341
   return (
331 342
     <MainStackComponent
332 343
       showIntro={showIntro !== false}
344
+      isloggedIn={isloggedIn}
333 345
       createTabNavigator={createTabNavigator}
334 346
     />
335 347
   );

+ 3
- 1
src/screens/Other/Settings/DashboardEditScreen.tsx View File

@@ -32,6 +32,7 @@ import {
32 32
 } from '../../../utils/Services';
33 33
 import { useNavigation } from '@react-navigation/core';
34 34
 import { useCurrentDashboard } from '../../../context/preferencesContext';
35
+import { useLoginState } from '../../../context/loginContext';
35 36
 
36 37
 const styles = StyleSheet.create({
37 38
   dashboardContainer: {
@@ -63,6 +64,7 @@ const styles = StyleSheet.create({
63 64
  */
64 65
 function DashboardEditScreen() {
65 66
   const navigation = useNavigation();
67
+  const isLoggedIn = useLoginState();
66 68
 
67 69
   const {
68 70
     currentDashboard,
@@ -150,7 +152,7 @@ function DashboardEditScreen() {
150 152
 
151 153
   return (
152 154
     <CollapsibleFlatList
153
-      data={getCategories(navigation.navigate)}
155
+      data={getCategories(navigation.navigate, isLoggedIn)}
154 156
       renderItem={getRenderItem}
155 157
       ListHeaderComponent={getListHeader()}
156 158
       style={{}}

+ 55
- 73
src/screens/Services/ServicesScreen.tsx View File

@@ -17,7 +17,7 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-import * as React from 'react';
20
+import React, { useLayoutEffect } from 'react';
21 21
 import { Image, StyleSheet, View } from 'react-native';
22 22
 import {
23 23
   Avatar,
@@ -25,10 +25,9 @@ import {
25 25
   Divider,
26 26
   List,
27 27
   TouchableRipple,
28
-  withTheme,
28
+  useTheme,
29 29
 } from 'react-native-paper';
30 30
 import i18n from 'i18n-js';
31
-import { StackNavigationProp } from '@react-navigation/stack';
32 31
 import CardList from '../../components/Lists/CardList/CardList';
33 32
 import MaterialHeaderButtons, {
34 33
   Item,
@@ -41,11 +40,8 @@ import {
41 40
   ServiceCategoryType,
42 41
   SERVICES_CATEGORIES_KEY,
43 42
 } from '../../utils/Services';
44
-
45
-type PropsType = {
46
-  navigation: StackNavigationProp<any>;
47
-  theme: ReactNativePaper.Theme;
48
-};
43
+import { useNavigation } from '@react-navigation/native';
44
+import { useLoginState } from '../../context/loginContext';
49 45
 
50 46
 const styles = StyleSheet.create({
51 47
   container: {
@@ -61,37 +57,29 @@ const styles = StyleSheet.create({
61 57
   },
62 58
 });
63 59
 
64
-class ServicesScreen extends React.Component<PropsType> {
65
-  finalDataset: Array<ServiceCategoryType>;
60
+function ServicesScreen() {
61
+  const navigation = useNavigation();
62
+  const theme = useTheme();
63
+  const isLoggedIn = useLoginState();
66 64
 
67
-  constructor(props: PropsType) {
68
-    super(props);
69
-    this.finalDataset = getCategories(props.navigation.navigate, [
70
-      SERVICES_CATEGORIES_KEY.SPECIAL,
71
-    ]);
72
-  }
65
+  const finalDataset = getCategories(navigation.navigate, isLoggedIn, [
66
+    SERVICES_CATEGORIES_KEY.SPECIAL,
67
+  ]);
73 68
 
74
-  componentDidMount() {
75
-    const { props } = this;
76
-    props.navigation.setOptions({
77
-      headerRight: this.getAboutButton,
69
+  useLayoutEffect(() => {
70
+    const getAboutButton = () => (
71
+      <MaterialHeaderButtons>
72
+        <Item
73
+          title="information"
74
+          iconName="information"
75
+          onPress={() => navigation.navigate('amicale-contact')}
76
+        />
77
+      </MaterialHeaderButtons>
78
+    );
79
+    navigation.setOptions({
80
+      headerRight: getAboutButton,
78 81
     });
79
-  }
80
-
81
-  getAboutButton = () => (
82
-    <MaterialHeaderButtons>
83
-      <Item
84
-        title="information"
85
-        iconName="information"
86
-        onPress={this.onAboutPress}
87
-      />
88
-    </MaterialHeaderButtons>
89
-  );
90
-
91
-  onAboutPress = () => {
92
-    const { props } = this;
93
-    props.navigation.navigate('amicale-contact');
94
-  };
82
+  }, [navigation]);
95 83
 
96 84
   /**
97 85
    * Gets the list title image for the list.
@@ -102,8 +90,7 @@ class ServicesScreen extends React.Component<PropsType> {
102 90
    * @param source The source image to display. Can be a string for icons or a number for local images
103 91
    * @returns {*}
104 92
    */
105
-  getListTitleImage(source: string | number) {
106
-    const { props } = this;
93
+  const getListTitleImage = (source: string | number) => {
107 94
     if (typeof source === 'number') {
108 95
       return <Image source={source} style={styles.image} />;
109 96
     }
@@ -111,11 +98,11 @@ class ServicesScreen extends React.Component<PropsType> {
111 98
       <Avatar.Icon
112 99
         size={48}
113 100
         icon={source}
114
-        color={props.theme.colors.primary}
101
+        color={theme.colors.primary}
115 102
         style={styles.icon}
116 103
       />
117 104
     );
118
-  }
105
+  };
119 106
 
120 107
   /**
121 108
    * A list item showing a list of available services for the current category
@@ -123,20 +110,17 @@ class ServicesScreen extends React.Component<PropsType> {
123 110
    * @param item
124 111
    * @returns {*}
125 112
    */
126
-  getRenderItem = ({ item }: { item: ServiceCategoryType }) => {
127
-    const { props } = this;
113
+  const getRenderItem = ({ item }: { item: ServiceCategoryType }) => {
128 114
     return (
129 115
       <TouchableRipple
130 116
         style={styles.container}
131
-        onPress={() => {
132
-          props.navigation.navigate('services-section', { data: item });
133
-        }}
117
+        onPress={() => navigation.navigate('services-section', { data: item })}
134 118
       >
135 119
         <View>
136 120
           <Card.Title
137 121
             title={item.title}
138 122
             subtitle={item.subtitle}
139
-            left={() => this.getListTitleImage(item.image)}
123
+            left={() => getListTitleImage(item.image)}
140 124
             right={() => <List.Icon icon="chevron-right" />}
141 125
           />
142 126
           <CardList dataset={item.content} isHorizontal />
@@ -145,33 +129,31 @@ class ServicesScreen extends React.Component<PropsType> {
145 129
     );
146 130
   };
147 131
 
148
-  keyExtractor = (item: ServiceCategoryType): string => item.title;
132
+  const keyExtractor = (item: ServiceCategoryType): string => item.title;
149 133
 
150
-  render() {
151
-    return (
152
-      <View>
153
-        <CollapsibleFlatList
154
-          data={this.finalDataset}
155
-          renderItem={this.getRenderItem}
156
-          keyExtractor={this.keyExtractor}
157
-          ItemSeparatorComponent={() => <Divider />}
158
-          hasTab
159
-        />
160
-        <MascotPopup
161
-          title={i18n.t('screens.services.mascotDialog.title')}
162
-          message={i18n.t('screens.services.mascotDialog.message')}
163
-          icon="cloud-question"
164
-          buttons={{
165
-            cancel: {
166
-              message: i18n.t('screens.services.mascotDialog.button'),
167
-              icon: 'check',
168
-            },
169
-          }}
170
-          emotion={MASCOT_STYLE.WINK}
171
-        />
172
-      </View>
173
-    );
174
-  }
134
+  return (
135
+    <View>
136
+      <CollapsibleFlatList
137
+        data={finalDataset}
138
+        renderItem={getRenderItem}
139
+        keyExtractor={keyExtractor}
140
+        ItemSeparatorComponent={() => <Divider />}
141
+        hasTab
142
+      />
143
+      <MascotPopup
144
+        title={i18n.t('screens.services.mascotDialog.title')}
145
+        message={i18n.t('screens.services.mascotDialog.message')}
146
+        icon="cloud-question"
147
+        buttons={{
148
+          cancel: {
149
+            message: i18n.t('screens.services.mascotDialog.button'),
150
+            icon: 'check',
151
+          },
152
+        }}
153
+        emotion={MASCOT_STYLE.WINK}
154
+      />
155
+    </View>
156
+  );
175 157
 }
176 158
 
177
-export default withTheme(ServicesScreen);
159
+export default ServicesScreen;

+ 18
- 4
src/utils/Services.ts View File

@@ -86,8 +86,21 @@ export type ServiceCategoryType = {
86 86
   content: Array<ServiceItemType>;
87 87
 };
88 88
 
89
+function getAmicaleOnPress(
90
+  route: string,
91
+  onPress: (route: string, params?: { [key: string]: any }) => void,
92
+  isLoggedIn: boolean
93
+) {
94
+  if (isLoggedIn) {
95
+    return () => onPress(route);
96
+  } else {
97
+    return () => onPress(MainRoutes.Login, { nextScreen: route });
98
+  }
99
+}
100
+
89 101
 export function getAmicaleServices(
90 102
   onPress: (route: string, params?: { [key: string]: any }) => void,
103
+  isLoggedIn: boolean,
91 104
   excludedItems?: Array<string>
92 105
 ): Array<ServiceItemType> {
93 106
   const amicaleDataset = [
@@ -96,21 +109,21 @@ export function getAmicaleServices(
96 109
       title: i18n.t('screens.clubs.title'),
97 110
       subtitle: i18n.t('screens.services.descriptions.clubs'),
98 111
       image: Urls.images.clubs,
99
-      onPress: () => onPress(MainRoutes.ClubList),
112
+      onPress: getAmicaleOnPress(MainRoutes.ClubList, onPress, isLoggedIn),
100 113
     },
101 114
     {
102 115
       key: SERVICES_KEY.PROFILE,
103 116
       title: i18n.t('screens.profile.title'),
104 117
       subtitle: i18n.t('screens.services.descriptions.profile'),
105 118
       image: Urls.images.profile,
106
-      onPress: () => onPress(MainRoutes.Profile),
119
+      onPress: getAmicaleOnPress(MainRoutes.Profile, onPress, isLoggedIn),
107 120
     },
108 121
     {
109 122
       key: SERVICES_KEY.EQUIPMENT,
110 123
       title: i18n.t('screens.equipment.title'),
111 124
       subtitle: i18n.t('screens.services.descriptions.equipment'),
112 125
       image: Urls.images.equipment,
113
-      onPress: () => onPress(MainRoutes.EquipmentList),
126
+      onPress: getAmicaleOnPress(MainRoutes.EquipmentList, onPress, isLoggedIn),
114 127
     },
115 128
     {
116 129
       key: SERVICES_KEY.AMICALE_WEBSITE,
@@ -289,6 +302,7 @@ export function getSpecialServices(
289 302
 
290 303
 export function getCategories(
291 304
   onPress: (route: string, params?: { [key: string]: any }) => void,
305
+  isLoggedIn: boolean,
292 306
   excludedItems?: Array<string>
293 307
 ): Array<ServiceCategoryType> {
294 308
   const categoriesDataset = [
@@ -297,7 +311,7 @@ export function getCategories(
297 311
       title: i18n.t('screens.services.categories.amicale'),
298 312
       subtitle: i18n.t('screens.services.more'),
299 313
       image: AMICALE_LOGO,
300
-      content: getAmicaleServices(onPress),
314
+      content: getAmicaleServices(onPress, isLoggedIn),
301 315
     },
302 316
     {
303 317
       key: SERVICES_CATEGORIES_KEY.STUDENTS,

Loading…
Cancel
Save