Browse Source

Update planning screens to use TypeScript

Arnaud Vergnet 1 year ago
parent
commit
b78357968a
2 changed files with 49 additions and 38 deletions
  1. 20
    14
      src/screens/Planning/PlanningDisplayScreen.tsx
  2. 29
    24
      src/screens/Planning/PlanningScreen.tsx

src/screens/Planning/PlanningDisplayScreen.js → src/screens/Planning/PlanningDisplayScreen.tsx View File

@@ -36,12 +36,12 @@ import type {PlanningEventType} from '../../utils/Planning';
36 36
 import ImageGalleryButton from '../../components/Media/ImageGalleryButton';
37 37
 
38 38
 type PropsType = {
39
-  navigation: StackNavigationProp,
40
-  route: {params: {data: PlanningEventType, id: number, eventId: number}},
39
+  navigation: StackNavigationProp<any>;
40
+  route: {params: {data: PlanningEventType; id: number; eventId: number}};
41 41
 };
42 42
 
43 43
 type StateType = {
44
-  loading: boolean,
44
+  loading: boolean;
45 45
 };
46 46
 
47 47
 const EVENT_INFO_URL = 'event/info';
@@ -111,22 +111,23 @@ class PlanningDisplayScreen extends React.Component<PropsType, StateType> {
111 111
    *
112 112
    * @returns {*}
113 113
    */
114
-  getContent(): React.Node {
115
-    const {navigation} = this.props;
114
+  getContent() {
116 115
     const {displayData} = this;
117
-    if (displayData == null) return null;
116
+    if (displayData == null) {
117
+      return null;
118
+    }
118 119
     let subtitle = getTimeOnlyString(displayData.date_begin);
119 120
     const dateString = getDateOnlyString(displayData.date_begin);
120
-    if (dateString !== null && subtitle != null)
121
+    if (dateString !== null && subtitle != null) {
121 122
       subtitle += ` | ${DateManager.getInstance().getTranslatedDate(
122 123
         dateString,
123 124
       )}`;
125
+    }
124 126
     return (
125 127
       <CollapsibleScrollView style={{paddingLeft: 5, paddingRight: 5}} hasTab>
126 128
         <Card.Title title={displayData.title} subtitle={subtitle} />
127 129
         {displayData.logo !== null ? (
128 130
           <ImageGalleryButton
129
-            navigation={navigation}
130 131
             images={[{url: displayData.logo}]}
131 132
             style={{
132 133
               width: 300,
@@ -154,9 +155,9 @@ class PlanningDisplayScreen extends React.Component<PropsType, StateType> {
154 155
    *
155 156
    * @returns {*}
156 157
    */
157
-  getErrorView(): React.Node {
158
+  getErrorView() {
158 159
     const {navigation} = this.props;
159
-    if (this.errorCode === ERROR_TYPE.BAD_INPUT)
160
+    if (this.errorCode === ERROR_TYPE.BAD_INPUT) {
160 161
       return (
161 162
         <ErrorView
162 163
           navigation={navigation}
@@ -165,6 +166,7 @@ class PlanningDisplayScreen extends React.Component<PropsType, StateType> {
165 166
           icon="calendar-remove"
166 167
         />
167 168
       );
169
+    }
168 170
     return (
169 171
       <ErrorView
170 172
         navigation={navigation}
@@ -179,15 +181,19 @@ class PlanningDisplayScreen extends React.Component<PropsType, StateType> {
179 181
    */
180 182
   fetchData = () => {
181 183
     this.setState({loading: true});
182
-    apiRequest(EVENT_INFO_URL, 'POST', {id: this.eventId})
184
+    apiRequest<PlanningEventType>(EVENT_INFO_URL, 'POST', {id: this.eventId})
183 185
       .then(this.onFetchSuccess)
184 186
       .catch(this.onFetchError);
185 187
   };
186 188
 
187
-  render(): React.Node {
189
+  render() {
188 190
     const {loading} = this.state;
189
-    if (loading) return <BasicLoadingScreen />;
190
-    if (this.errorCode === 0) return this.getContent();
191
+    if (loading) {
192
+      return <BasicLoadingScreen />;
193
+    }
194
+    if (this.errorCode === 0) {
195
+      return this.getContent();
196
+    }
191 197
     return this.getErrorView();
192 198
   }
193 199
 }

src/screens/Planning/PlanningScreen.js → src/screens/Planning/PlanningScreen.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 {BackHandler, View} from 'react-native';
24 22
 import i18n from 'i18n-js';
@@ -26,12 +24,12 @@ import {Agenda, LocaleConfig} from 'react-native-calendars';
26 24
 import {Avatar, Divider, List} from 'react-native-paper';
27 25
 import {StackNavigationProp} from '@react-navigation/stack';
28 26
 import {readData} from '../../utils/WebData';
29
-import type {PlanningEventType} from '../../utils/Planning';
30 27
 import {
31 28
   generateEventAgenda,
32 29
   getCurrentDateString,
33 30
   getDateOnlyString,
34 31
   getTimeOnlyString,
32
+  PlanningEventType,
35 33
 } from '../../utils/Planning';
36 34
 import CustomAgenda from '../../components/Overrides/CustomAgenda';
37 35
 import {MASCOT_STYLE} from '../../components/Mascot/Mascot';
@@ -77,17 +75,16 @@ LocaleConfig.locales.fr = {
77 75
     'Samedi',
78 76
   ],
79 77
   dayNamesShort: ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'],
80
-  today: "Aujourd'hui",
81 78
 };
82 79
 
83 80
 type PropsType = {
84
-  navigation: StackNavigationProp,
81
+  navigation: StackNavigationProp<any>;
85 82
 };
86 83
 
87 84
 type StateType = {
88
-  refreshing: boolean,
89
-  agendaItems: {[key: string]: Array<PlanningEventType>},
90
-  calendarShowing: boolean,
85
+  refreshing: boolean;
86
+  agendaItems: {[key: string]: Array<PlanningEventType>};
87
+  calendarShowing: boolean;
91 88
 };
92 89
 
93 90
 const FETCH_URL = 'https://www.amicale-insat.fr/api/event/list';
@@ -97,19 +94,22 @@ const AGENDA_MONTH_SPAN = 3;
97 94
  * Class defining the app's planning screen
98 95
  */
99 96
 class PlanningScreen extends React.Component<PropsType, StateType> {
100
-  agendaRef: null | Agenda;
97
+  agendaRef: null | Agenda<any>;
101 98
 
102
-  lastRefresh: Date;
99
+  lastRefresh: Date | null;
103 100
 
104 101
   minTimeBetweenRefresh = 60;
105 102
 
106
-  currentDate = getDateOnlyString(getCurrentDateString());
103
+  currentDate: string | null;
107 104
 
108 105
   constructor(props: PropsType) {
109 106
     super(props);
110 107
     if (i18n.currentLocale().startsWith('fr')) {
111 108
       LocaleConfig.defaultLocale = 'fr';
112 109
     }
110
+    this.agendaRef = null;
111
+    this.currentDate = getDateOnlyString(getCurrentDateString());
112
+    this.lastRefresh = null;
113 113
     this.state = {
114 114
       refreshing: false,
115 115
       agendaItems: {},
@@ -145,6 +145,7 @@ class PlanningScreen extends React.Component<PropsType, StateType> {
145 145
   onBackButtonPressAndroid = (): boolean => {
146 146
     const {calendarShowing} = this.state;
147 147
     if (calendarShowing && this.agendaRef != null) {
148
+      // @ts-ignore
148 149
       this.agendaRef.chooseDay(this.agendaRef.state.selectedDay);
149 150
       return true;
150 151
     }
@@ -156,11 +157,13 @@ class PlanningScreen extends React.Component<PropsType, StateType> {
156 157
    */
157 158
   onRefresh = () => {
158 159
     let canRefresh;
159
-    if (this.lastRefresh !== undefined)
160
+    if (this.lastRefresh) {
160 161
       canRefresh =
161 162
         (new Date().getTime() - this.lastRefresh.getTime()) / 1000 >
162 163
         this.minTimeBetweenRefresh;
163
-    else canRefresh = true;
164
+    } else {
165
+      canRefresh = true;
166
+    }
164 167
 
165 168
     if (canRefresh) {
166 169
       this.setState({refreshing: true});
@@ -185,7 +188,7 @@ class PlanningScreen extends React.Component<PropsType, StateType> {
185 188
    *
186 189
    * @param ref
187 190
    */
188
-  onAgendaRef = (ref: Agenda) => {
191
+  onAgendaRef = (ref: Agenda<any>) => {
189 192
     this.agendaRef = ref;
190 193
   };
191 194
 
@@ -204,23 +207,24 @@ class PlanningScreen extends React.Component<PropsType, StateType> {
204 207
    * @param item The current event to render
205 208
    * @return {*}
206 209
    */
207
-  getRenderItem = (item: PlanningEventType): React.Node => {
210
+  getRenderItem = (item: PlanningEventType) => {
208 211
     const {navigation} = this.props;
209 212
     const onPress = () => {
210 213
       navigation.navigate('planning-information', {
211 214
         data: item,
212 215
       });
213 216
     };
214
-    if (item.logo !== null) {
217
+    const logo = item.logo;
218
+    if (logo) {
215 219
       return (
216 220
         <View>
217 221
           <Divider />
218 222
           <List.Item
219 223
             title={item.title}
220 224
             description={getTimeOnlyString(item.date_begin)}
221
-            left={(): React.Node => (
225
+            left={() => (
222 226
               <Avatar.Image
223
-                source={{uri: item.logo}}
227
+                source={{uri: logo}}
224 228
                 style={{backgroundColor: 'transparent'}}
225 229
               />
226 230
             )}
@@ -246,23 +250,22 @@ class PlanningScreen extends React.Component<PropsType, StateType> {
246 250
    *
247 251
    * @return {*}
248 252
    */
249
-  getRenderEmptyDate = (): React.Node => <Divider />;
253
+  getRenderEmptyDate = () => <Divider />;
250 254
 
251
-  render(): React.Node {
255
+  render() {
252 256
     const {state, props} = this;
253 257
     return (
254 258
       <View style={{flex: 1}}>
255 259
         <CustomAgenda
256
-          // eslint-disable-next-line react/jsx-props-no-spreading
257 260
           {...props}
258 261
           // the list of items that have to be displayed in agenda. If you want to render item as empty date
259 262
           // the value of date key kas to be an empty array []. If there exists no value for date key it is
260 263
           // considered that the date in question is not yet loaded
261 264
           items={state.agendaItems}
262 265
           // initially selected day
263
-          selected={this.currentDate}
266
+          selected={this.currentDate ? this.currentDate : undefined}
264 267
           // Minimum date that can be selected, dates before minDate will be grayed out. Default = undefined
265
-          minDate={this.currentDate}
268
+          minDate={this.currentDate ? this.currentDate : undefined}
266 269
           // Max amount of months allowed to scroll to the past. Default = 50
267 270
           pastScrollRange={1}
268 271
           // Max amount of months allowed to scroll to the future. Default = 50
@@ -279,6 +282,9 @@ class PlanningScreen extends React.Component<PropsType, StateType> {
279 282
           firstDay={1}
280 283
           // ref to this agenda in order to handle back button event
281 284
           onRef={this.onAgendaRef}
285
+          rowHasChanged={(r1: PlanningEventType, r2: PlanningEventType) =>
286
+            r1.id !== r2.id
287
+          }
282 288
         />
283 289
         <MascotPopup
284 290
           prefKey={AsyncStorageManager.PREFERENCES.eventsShowMascot.key}
@@ -286,7 +292,6 @@ class PlanningScreen extends React.Component<PropsType, StateType> {
286 292
           message={i18n.t('screens.planning.mascotDialog.message')}
287 293
           icon="party-popper"
288 294
           buttons={{
289
-            action: null,
290 295
             cancel: {
291 296
               message: i18n.t('screens.planning.mascotDialog.button'),
292 297
               icon: 'check',

Loading…
Cancel
Save