|
@@ -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',
|