Browse Source

Improved dashboard display and translations

keplyx 2 years ago
parent
commit
98e820473e
4 changed files with 222 additions and 77 deletions
  1. 206
    68
      screens/HomeScreen.js
  2. 2
    3
      screens/Proxiwash/ProxiwashScreen.js
  3. 8
    4
      translations/en.json
  4. 6
    2
      translations/fr.json

+ 206
- 68
screens/HomeScreen.js View File

@@ -2,7 +2,7 @@
2 2
 
3 3
 import * as React from 'react';
4 4
 import {Image, Linking, TouchableOpacity, View} from 'react-native';
5
-import {Body, Button, Card, CardItem, Left, Right, Text, Thumbnail, H1, H3, Content} from 'native-base';
5
+import {Body, Button, Card, CardItem, Left, Text, Thumbnail, H1, H3} from 'native-base';
6 6
 import i18n from "i18n-js";
7 7
 import CustomMaterialIcon from '../components/CustomMaterialIcon';
8 8
 import FetchedDataSectionList from "../components/FetchedDataSectionList";
@@ -12,6 +12,8 @@ import PlatformTouchable from "react-native-platform-touchable";
12 12
 import HTML from 'react-native-render-html';
13 13
 import {LinearGradient} from 'expo-linear-gradient';
14 14
 
15
+import DATA from '../data_test'
16
+
15 17
 
16 18
 const ICON_AMICALE = require('../assets/amicale.png');
17 19
 const NAME_AMICALE = 'Amicale INSA Toulouse';
@@ -22,6 +24,8 @@ const SECTIONS_ID = [
22 24
     'news_feed'
23 25
 ];
24 26
 
27
+const REFRESH_TIME = 1000 * 10; // Refresh every 10 seconds
28
+
25 29
 
26 30
 /**
27 31
  * Opens a link in the device's browser
@@ -37,7 +41,7 @@ function openWebLink(link) {
37 41
 export default class HomeScreen extends FetchedDataSectionList {
38 42
 
39 43
     constructor() {
40
-        super(DATA_URL, 0);
44
+        super('DATA_URL', REFRESH_TIME);
41 45
     }
42 46
 
43 47
     getHeaderTranslation() {
@@ -53,6 +57,7 @@ export default class HomeScreen extends FetchedDataSectionList {
53 57
     }
54 58
 
55 59
     createDataset(fetchedData: Object) {
60
+        fetchedData = DATA;
56 61
         let newsData = [];
57 62
         let dashboardData = [];
58 63
         if (fetchedData['news_feed'] !== undefined)
@@ -81,7 +86,7 @@ export default class HomeScreen extends FetchedDataSectionList {
81 86
         let dataset = [
82 87
             {
83 88
                 id: 'top',
84
-                content: {}
89
+                content: undefined
85 90
             },
86 91
             {
87 92
                 id: 'middle',
@@ -89,7 +94,7 @@ export default class HomeScreen extends FetchedDataSectionList {
89 94
             },
90 95
             {
91 96
                 id: 'bottom',
92
-                content: {}
97
+                content: undefined
93 98
             },
94 99
 
95 100
         ];
@@ -152,46 +157,150 @@ export default class HomeScreen extends FetchedDataSectionList {
152 157
             return this.getDashboardBottomItem(content);
153 158
     }
154 159
 
155
-    getDisplayEvent(events: Array<Object>): Object {
156
-        let displayEvent = undefined;
160
+    /**
161
+     * Convert the date string given by in the event list json to a date object
162
+     * @param dateString
163
+     * @return {Date}
164
+     */
165
+    stringToDate(dateString: ?string): ?Date {
166
+        let date = new Date();
167
+        if (dateString === undefined || dateString === null)
168
+            date = undefined;
169
+        else if (dateString.split(' ').length > 1) {
170
+            let timeStr = dateString.split(' ')[1];
171
+            date.setHours(parseInt(timeStr.split(':')[0]), parseInt(timeStr.split(':')[1]), 0);
172
+        } else
173
+            date = undefined;
174
+        return date;
175
+    }
157 176
 
158
-        if (events.length === 1) {
159
-            displayEvent = this.getEventDisplayData(events[0]);
160
-        } else {
161
-            for (let event of events) {
162
-                if (event['date_begin'] === undefined || event['date_end'] === undefined)
163
-                    continue;
164
-
165
-                let date_begin = event['date_begin'].split(' ')[1];
166
-                let date_end = event['date_end'].split(' ')[1];
167
-                let startDate = new Date();
168
-                let endDate = new Date();
169
-                let limit = new Date();
170
-                let now = new Date();
171
-                startDate.setHours(parseInt(date_begin.split(':')[0]), date_begin.split(':')[1], 0);
172
-                endDate.setHours(parseInt(date_end.split(':')[0]), date_end.split(':')[1], 0);
173
-                limit.setHours(18, 0, 0); // Only display events after 18:00 as these are the most important
174
-                if (limit.getTime() < startDate.getTime() && now.getTime() < endDate.getTime()) {
175
-                    displayEvent = this.getEventDisplayData(event);
176
-                    break;
177
-                }
177
+    /**
178
+     * Get the time limit depending on the current day:
179
+     * 17:30 for every day of the week except for thursday 11:30
180
+     * 00:00 on weekends
181
+     */
182
+    getTodayEventTimeLimit() {
183
+        let now = new Date();
184
+        if (now.getDay() === 4) // Thursday
185
+            now.setHours(11, 30, 0);
186
+        else if (now.getDay() === 6 || now.getDay() === 0) // Weekend
187
+            now.setHours(0, 0, 0);
188
+        else
189
+            now.setHours(17, 30, 0);
190
+        return now;
191
+    }
192
+
193
+    /**
194
+     * Get the duration (in milliseconds) of an event
195
+     * @param event {Object}
196
+     * @return {number} The number of milliseconds
197
+     */
198
+    getEventDuration(event: Object): number {
199
+        let start = this.stringToDate(event['date_begin']);
200
+        let end = this.stringToDate(event['date_end']);
201
+        let duration = 0;
202
+        if (start !== undefined && start !== null && end !== undefined && end !== null)
203
+            duration = end - start;
204
+        return duration;
205
+    }
206
+
207
+    /**
208
+     * Get events starting after the limit
209
+     *
210
+     * @param events
211
+     * @param limit
212
+     * @return {Array<Object>}
213
+     */
214
+    getEventsAfterLimit(events: Object, limit: Date): Array<Object> {
215
+        let validEvents = [];
216
+        for (let event of events) {
217
+            let startDate = this.stringToDate(event['date_begin']);
218
+            if (startDate !== undefined && startDate !== null && startDate >= limit) {
219
+                validEvents.push(event);
178 220
             }
179 221
         }
180
-        return displayEvent;
222
+        return validEvents;
223
+    }
224
+
225
+    /**
226
+     * Get the event with the longest duration in the given array.
227
+     * If all events have the same duration, return the first in the array.
228
+     * @param events
229
+     */
230
+    getLongestEvent(events: Array<Object>): Object {
231
+        let longestEvent = events[0];
232
+        let longestTime = 0;
233
+        for (let event of events) {
234
+            let time = this.getEventDuration(event);
235
+            if (time > longestTime) {
236
+                longestTime = time;
237
+                longestEvent = event;
238
+            }
239
+        }
240
+        return longestEvent;
181 241
     }
182 242
 
183
-    getEventDisplayData(event: Object): Object {
184
-        let date = '';
185
-        if (event['date_begin'].split(' ').length > 2) {
186
-            date = event['date_begin'].split(' ')[1];
187
-            date = date.split(':')[0] + ':' + date.split(':')[1];
243
+    /**
244
+     * Get events that have not yet ended/started
245
+     *
246
+     * @param events
247
+     */
248
+    getFutureEvents(events: Array<Object>): Array<Object> {
249
+        let validEvents = [];
250
+        let now = new Date();
251
+        for (let event of events) {
252
+            let startDate = this.stringToDate(event['date_begin']);
253
+            let endDate = this.stringToDate(event['date_end']);
254
+            if (startDate !== undefined && startDate !== null) {
255
+                if (startDate > now)
256
+                    validEvents.push(event);
257
+                else if (endDate !== undefined && endDate !== null) {
258
+                    if (endDate > now)
259
+                        validEvents.push(event);
260
+                }
261
+            }
188 262
         }
189
-        return {
190
-            logo: event['logo'],
191
-            title: event['title'],
192
-            date: date,
193
-            description: event['description'],
263
+        return validEvents;
264
+    }
265
+
266
+    /**
267
+     *
268
+     *
269
+     * @param events
270
+     * @return {Object}
271
+     */
272
+    getDisplayEvent(events: Array<Object>): Object {
273
+        let displayEvent = undefined;
274
+        if (events.length > 1) {
275
+            let eventsAfterLimit = this.getEventsAfterLimit(events, this.getTodayEventTimeLimit());
276
+            if (eventsAfterLimit.length > 0) {
277
+                if (eventsAfterLimit.length === 1)
278
+                    displayEvent = eventsAfterLimit[0];
279
+                else
280
+                    displayEvent = this.getLongestEvent(events);
281
+            } else {
282
+                displayEvent = this.getLongestEvent(events);
283
+            }
284
+        } else if (events.length === 1) {
285
+            displayEvent = events[0];
194 286
         }
287
+        return displayEvent;
288
+    }
289
+
290
+    padStr(i: number) {
291
+        return (i < 10) ? "0" + i : "" + i;
292
+    }
293
+
294
+    getFormattedEventTime(event: Object): string {
295
+        let formattedStr = '';
296
+        let startDate = this.stringToDate(event['date_begin']);
297
+        let endDate = this.stringToDate(event['date_end']);
298
+        if (startDate !== undefined && startDate !== null && endDate !== undefined && endDate !== null)
299
+            formattedStr = this.padStr(startDate.getHours()) + ':' + this.padStr(startDate.getMinutes()) +
300
+                ' - ' + this.padStr(endDate.getHours()) + ':' + this.padStr(endDate.getMinutes());
301
+        else if (startDate !== undefined && startDate !== null)
302
+            formattedStr = this.padStr(startDate.getHours()) + ':' + this.padStr(startDate.getMinutes());
303
+        return formattedStr
195 304
     }
196 305
 
197 306
 
@@ -201,36 +310,43 @@ export default class HomeScreen extends FetchedDataSectionList {
201 310
         let title = i18n.t('homeScreen.dashboard.todayEventsTitle');
202 311
         let isAvailable = content.length > 0;
203 312
         let subtitle = '';
313
+        let futureEvents = this.getFutureEvents(content);
204 314
         if (isAvailable) {
205 315
             subtitle =
206 316
                 <Text>
207
-                    <Text style={{fontWeight: "bold"}}>{content.length}</Text>
208
-                    <Text>{i18n.t('homeScreen.dashboard.todayEventsSubtitle')}</Text>
317
+                    <Text style={{fontWeight: "bold"}}>{futureEvents.length}</Text>
318
+                    <Text>
319
+                        {
320
+                            futureEvents.length > 1 ?
321
+                                i18n.t('homeScreen.dashboard.todayEventsSubtitlePlural') :
322
+                                i18n.t('homeScreen.dashboard.todayEventsSubtitle')
323
+                        }
324
+                    </Text>
209 325
                 </Text>;
210 326
         } else
211 327
             subtitle = i18n.t('homeScreen.dashboard.todayEventsSubtitleNA');
212 328
         let clickAction = () => this.props.navigation.navigate('Planning');
213 329
 
214
-        let displayEvent = this.getDisplayEvent(content);
330
+        let displayEvent = this.getDisplayEvent(futureEvents);
215 331
 
216 332
         return (
217 333
             <Card style={{
218 334
                 flex: 0,
219 335
                 marginLeft: 10,
220 336
                 marginRight: 10,
221
-                borderRadius: 30,
222
-                backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg
337
+                marginTop: 10,
338
+                borderRadius: 20,
339
+                backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg,
340
+                overflow: 'hidden',
223 341
             }}>
224 342
                 <PlatformTouchable
225 343
                     onPress={clickAction}
226 344
                     style={{
227 345
                         zIndex: 100,
228
-                        borderRadius: 30
229 346
                     }}
230 347
                 >
231 348
                     <View>
232 349
                         <CardItem style={{
233
-                            borderRadius: 30,
234 350
                             backgroundColor: 'transparent',
235 351
                         }}>
236 352
                             <Left>
@@ -265,7 +381,8 @@ export default class HomeScreen extends FetchedDataSectionList {
265 381
                             <View>
266 382
                                 <CardItem style={{
267 383
                                     paddingTop: 0,
268
-                                    paddingBottom: 0
384
+                                    paddingBottom: 0,
385
+                                    backgroundColor: 'transparent',
269 386
                                 }}>
270 387
                                     <Left>
271 388
                                         {displayEvent['logo'] !== '' && displayEvent['logo'] !== null ?
@@ -273,7 +390,7 @@ export default class HomeScreen extends FetchedDataSectionList {
273 390
                                             <View/>}
274 391
                                         <Body>
275 392
                                             <Text>{displayEvent['title']}</Text>
276
-                                            <Text note>{displayEvent['date']}</Text>
393
+                                            <Text note>{this.getFormattedEventTime(displayEvent)}</Text>
277 394
                                         </Body>
278 395
                                     </Left>
279 396
                                 </CardItem>
@@ -282,7 +399,7 @@ export default class HomeScreen extends FetchedDataSectionList {
282 399
                                     backgroundColor: 'transparent',
283 400
                                 }}>
284 401
                                     <Body style={{
285
-                                        height: 70,
402
+                                        height: displayEvent['description'].length > 50 ? 70 : 20,
286 403
                                         overflow: 'hidden',
287 404
                                     }}>
288 405
                                         <HTML html={"<div>" + displayEvent['description'] + "</div>"}
@@ -301,7 +418,7 @@ export default class HomeScreen extends FetchedDataSectionList {
301 418
                                                 position: 'absolute',
302 419
                                                 width: '100%',
303 420
                                                 height: 60,
304
-                                                bottom: 0
421
+                                                bottom: 0,
305 422
                                             }}>
306 423
                                             <View style={{
307 424
                                                 marginLeft: 'auto',
@@ -328,25 +445,25 @@ export default class HomeScreen extends FetchedDataSectionList {
328 445
         );
329 446
     }
330 447
 
331
-    getSquareDashboardItem(isAvailable: boolean, icon: string, color: string, title: string, subtitle: string, clickAction: Function, isLeftElement: boolean) {
448
+    getSquareDashboardItem(isAvailable: boolean, icon: string, color: string, title: string, subtitle: React.Node, clickAction: Function, isLeftElement: boolean) {
332 449
         return (
333 450
             <Card style={{
334 451
                 flex: 0,
335 452
                 width: '48%',
336 453
                 marginLeft: 0,
337 454
                 marginRight: isLeftElement ? '4%' : 0,
338
-                borderRadius: 30,
339
-                backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg
455
+                borderRadius: 20,
456
+                backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg,
457
+                overflow: 'hidden',
340 458
             }}>
341 459
                 <PlatformTouchable
342 460
                     onPress={clickAction}
343 461
                     style={{
344 462
                         zIndex: 100,
345
-                        borderRadius: 30
463
+                        minHeight: 150,
346 464
                     }}
347 465
                 >
348 466
                     <CardItem style={{
349
-                        borderRadius: 30,
350 467
                         backgroundColor: 'transparent'
351 468
                     }}>
352 469
                         <Body>
@@ -398,7 +515,13 @@ export default class HomeScreen extends FetchedDataSectionList {
398 515
             proximoSubtitle =
399 516
                 <Text>
400 517
                     <Text style={{fontWeight: "bold"}}>{proximoData}</Text>
401
-                    <Text>{i18n.t('homeScreen.dashboard.proximoSubtitle')}</Text>
518
+                    <Text>
519
+                        {
520
+                            proximoData > 1 ?
521
+                            i18n.t('homeScreen.dashboard.proximoSubtitlePlural') :
522
+                            i18n.t('homeScreen.dashboard.proximoSubtitle')
523
+                        }
524
+                    </Text>
402 525
                 </Text>;
403 526
         } else
404 527
             proximoSubtitle = i18n.t('homeScreen.dashboard.proximoSubtitleNA');
@@ -434,6 +557,14 @@ export default class HomeScreen extends FetchedDataSectionList {
434 557
         let title = i18n.t('homeScreen.dashboard.proxiwashTitle');
435 558
         let isAvailable = parseInt(content['dryers']) > 0 || parseInt(content['washers']) > 0;
436 559
         let subtitle;
560
+        let dryerColor = parseInt(content['dryers']) > 0 ?
561
+            ThemeManager.getCurrentThemeVariables().textColor :
562
+            ThemeManager.getCurrentThemeVariables().listNoteColor;
563
+        let washerColor = parseInt(content['washers']) > 0 ?
564
+            ThemeManager.getCurrentThemeVariables().textColor :
565
+            ThemeManager.getCurrentThemeVariables().listNoteColor;
566
+        let availableDryers = content['dryers'];
567
+        let availableWashers = content['washers'];
437 568
         if (isAvailable) {
438 569
             subtitle =
439 570
                 <Text>
@@ -441,24 +572,32 @@ export default class HomeScreen extends FetchedDataSectionList {
441 572
                         fontWeight: parseInt(content['dryers']) > 0 ?
442 573
                             'bold' :
443 574
                             'normal',
444
-                        color: parseInt(content['dryers']) > 0 ?
445
-                            ThemeManager.getCurrentThemeVariables().textColor :
446
-                            ThemeManager.getCurrentThemeVariables().listNoteColor
575
+                        color: dryerColor
447 576
                     }}>
448
-                        {content['dryers']}
577
+                        {availableDryers}
578
+                    </Text>
579
+                    <Text>
580
+                        {
581
+                            availableDryers > 1 ?
582
+                                i18n.t('homeScreen.dashboard.proxiwashSubtitle1Plural') :
583
+                                i18n.t('homeScreen.dashboard.proxiwashSubtitle1')
584
+                        }
449 585
                     </Text>
450
-                    <Text>{i18n.t('homeScreen.dashboard.proxiwashSubtitle1')}</Text>
451 586
                     <Text style={{
452 587
                         fontWeight: parseInt(content['washers']) > 0 ?
453 588
                             'bold' :
454 589
                             'normal',
455
-                        color: parseInt(content['washers']) > 0 ?
456
-                            ThemeManager.getCurrentThemeVariables().textColor :
457
-                            ThemeManager.getCurrentThemeVariables().listNoteColor
590
+                        color: washerColor
458 591
                     }}>
459
-                        {content['washers']}
592
+                        {availableWashers}
593
+                    </Text>
594
+                    <Text>
595
+                        {
596
+                            availableWashers > 1 ?
597
+                                i18n.t('homeScreen.dashboard.proxiwashSubtitle2Plural') :
598
+                                i18n.t('homeScreen.dashboard.proxiwashSubtitle2')
599
+                        }
460 600
                     </Text>
461
-                    <Text>{i18n.t('homeScreen.dashboard.proxiwashSubtitle2')}</Text>
462 601
                 </Text>;
463 602
         } else
464 603
             subtitle = i18n.t('homeScreen.dashboard.proxiwashSubtitleNA');
@@ -468,18 +607,17 @@ export default class HomeScreen extends FetchedDataSectionList {
468 607
                 flex: 0,
469 608
                 marginLeft: 10,
470 609
                 marginRight: 10,
471
-                borderRadius: 50,
472
-                backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg
610
+                borderRadius: 20,
611
+                backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg,
612
+                overflow: 'hidden',
473 613
             }}>
474 614
                 <PlatformTouchable
475 615
                     onPress={clickAction}
476 616
                     style={{
477 617
                         zIndex: 100,
478
-                        borderRadius: 50
479 618
                     }}
480 619
                 >
481 620
                     <CardItem style={{
482
-                        borderRadius: 50,
483 621
                         backgroundColor: 'transparent'
484 622
                     }}>
485 623
                         <Left>

+ 2
- 3
screens/Proxiwash/ProxiwashScreen.js View File

@@ -28,6 +28,7 @@ let modalStateStrings = {};
28 28
 let stateIcons = {};
29 29
 let stateColors = {};
30 30
 
31
+const REFRESH_TIME = 1000 * 10; // Refresh every 10 seconds
31 32
 
32 33
 /**
33 34
  * Class defining the app's proxiwash screen. This screen shows information about washing machines and
@@ -35,13 +36,11 @@ let stateColors = {};
35 36
  */
36 37
 export default class ProxiwashScreen extends FetchedDataSectionList {
37 38
 
38
-    refreshInterval: IntervalID;
39
-
40 39
     /**
41 40
      * Creates machine state parameters using current theme and translations
42 41
      */
43 42
     constructor() {
44
-        super(DATA_URL, 1000 * 30); // Refresh every half minute
43
+        super(DATA_URL, REFRESH_TIME);
45 44
         let colors = ThemeManager.getCurrentThemeVariables();
46 45
         stateColors[MACHINE_STATES.TERMINE] = colors.proxiwashFinishedColor;
47 46
         stateColors[MACHINE_STATES.DISPONIBLE] = colors.proxiwashReadyColor;

+ 8
- 4
translations/en.json View File

@@ -74,14 +74,18 @@
74 74
     "dashboard": {
75 75
       "todayEventsTitle": "Today's events",
76 76
       "todayEventsSubtitleNA": "No events today",
77
-      "todayEventsSubtitle": " events today",
77
+      "todayEventsSubtitle": " event coming today",
78
+      "todayEventsSubtitlePlural": " events coming today",
78 79
       "proximoTitle": "Proximo",
79 80
       "proximoSubtitleNA": "No articles available",
80
-      "proximoSubtitle": " articles available",
81
+      "proximoSubtitle": " article available",
82
+      "proximoSubtitlePlural": " articles available",
81 83
       "proxiwashTitle": "Available machines",
82 84
       "proxiwashSubtitleNA": "No machines available",
83
-      "proxiwashSubtitle1": " dryers and ",
84
-      "proxiwashSubtitle2": " washers",
85
+      "proxiwashSubtitle1": " dryer and ",
86
+      "proxiwashSubtitle1Plural": " dryers and ",
87
+      "proxiwashSubtitle2": " washer",
88
+      "proxiwashSubtitle2Plural": " washers",
85 89
       "menuTitle": "Today's menu",
86 90
       "menuSubtitleNA": "No menu available",
87 91
       "menuSubtitle": "Click here to see the menu"

+ 6
- 2
translations/fr.json View File

@@ -74,14 +74,18 @@
74 74
     "dashboard": {
75 75
       "todayEventsTitle": "Événements aujourd'hui",
76 76
       "todayEventsSubtitleNA": "Pas d'événements",
77
-      "todayEventsSubtitle": " événements aujourd'hui",
77
+      "todayEventsSubtitle": " événement aujourd'hui",
78
+      "todayEventsSubtitlePlural": " événements aujourd'hui",
78 79
       "proximoTitle": "Proximo",
79 80
       "proximoSubtitleNA": "pas d'article en vente",
80
-      "proximoSubtitle": " articles disponibles",
81
+      "proximoSubtitle": " article disponible",
82
+      "proximoSubtitlePlural": " articles disponibles",
81 83
       "proxiwashTitle": "Machines disponibles",
82 84
       "proxiwashSubtitleNA": "Pas de machine disponible",
83 85
       "proxiwashSubtitle1": " sèches linges et ",
86
+      "proxiwashSubtitle1Plural": " sèche linge et ",
84 87
       "proxiwashSubtitle2": " laves linges",
88
+      "proxiwashSubtitle2Plural": " lave linge",
85 89
       "menuTitle": "Menu d'aujourd'hui",
86 90
       "menuSubtitleNA": "Pas de menu disponible",
87 91
       "menuSubtitle": "Cliquez ici pour voir le menu"

Loading…
Cancel
Save