diff --git a/screens/HomeScreen.js b/screens/HomeScreen.js index 37b3220..9287280 100644 --- a/screens/HomeScreen.js +++ b/screens/HomeScreen.js @@ -2,7 +2,7 @@ import * as React from 'react'; import {Image, Linking, TouchableOpacity, View} from 'react-native'; -import {Body, Button, Card, CardItem, Left, Right, Text, Thumbnail, H1, H3, Content} from 'native-base'; +import {Body, Button, Card, CardItem, Left, Text, Thumbnail, H1, H3} from 'native-base'; import i18n from "i18n-js"; import CustomMaterialIcon from '../components/CustomMaterialIcon'; import FetchedDataSectionList from "../components/FetchedDataSectionList"; @@ -12,6 +12,8 @@ import PlatformTouchable from "react-native-platform-touchable"; import HTML from 'react-native-render-html'; import {LinearGradient} from 'expo-linear-gradient'; +import DATA from '../data_test' + const ICON_AMICALE = require('../assets/amicale.png'); const NAME_AMICALE = 'Amicale INSA Toulouse'; @@ -22,6 +24,8 @@ const SECTIONS_ID = [ 'news_feed' ]; +const REFRESH_TIME = 1000 * 10; // Refresh every 10 seconds + /** * Opens a link in the device's browser @@ -37,7 +41,7 @@ function openWebLink(link) { export default class HomeScreen extends FetchedDataSectionList { constructor() { - super(DATA_URL, 0); + super('DATA_URL', REFRESH_TIME); } getHeaderTranslation() { @@ -53,6 +57,7 @@ export default class HomeScreen extends FetchedDataSectionList { } createDataset(fetchedData: Object) { + fetchedData = DATA; let newsData = []; let dashboardData = []; if (fetchedData['news_feed'] !== undefined) @@ -81,7 +86,7 @@ export default class HomeScreen extends FetchedDataSectionList { let dataset = [ { id: 'top', - content: {} + content: undefined }, { id: 'middle', @@ -89,7 +94,7 @@ export default class HomeScreen extends FetchedDataSectionList { }, { id: 'bottom', - content: {} + content: undefined }, ]; @@ -152,46 +157,150 @@ export default class HomeScreen extends FetchedDataSectionList { return this.getDashboardBottomItem(content); } - getDisplayEvent(events: Array): Object { - let displayEvent = undefined; + /** + * Convert the date string given by in the event list json to a date object + * @param dateString + * @return {Date} + */ + stringToDate(dateString: ?string): ?Date { + let date = new Date(); + if (dateString === undefined || dateString === null) + date = undefined; + else if (dateString.split(' ').length > 1) { + let timeStr = dateString.split(' ')[1]; + date.setHours(parseInt(timeStr.split(':')[0]), parseInt(timeStr.split(':')[1]), 0); + } else + date = undefined; + return date; + } - if (events.length === 1) { - displayEvent = this.getEventDisplayData(events[0]); - } else { - for (let event of events) { - if (event['date_begin'] === undefined || event['date_end'] === undefined) - continue; + /** + * Get the time limit depending on the current day: + * 17:30 for every day of the week except for thursday 11:30 + * 00:00 on weekends + */ + getTodayEventTimeLimit() { + let now = new Date(); + if (now.getDay() === 4) // Thursday + now.setHours(11, 30, 0); + else if (now.getDay() === 6 || now.getDay() === 0) // Weekend + now.setHours(0, 0, 0); + else + now.setHours(17, 30, 0); + return now; + } - let date_begin = event['date_begin'].split(' ')[1]; - let date_end = event['date_end'].split(' ')[1]; - let startDate = new Date(); - let endDate = new Date(); - let limit = new Date(); - let now = new Date(); - startDate.setHours(parseInt(date_begin.split(':')[0]), date_begin.split(':')[1], 0); - endDate.setHours(parseInt(date_end.split(':')[0]), date_end.split(':')[1], 0); - limit.setHours(18, 0, 0); // Only display events after 18:00 as these are the most important - if (limit.getTime() < startDate.getTime() && now.getTime() < endDate.getTime()) { - displayEvent = this.getEventDisplayData(event); - break; + /** + * Get the duration (in milliseconds) of an event + * @param event {Object} + * @return {number} The number of milliseconds + */ + getEventDuration(event: Object): number { + let start = this.stringToDate(event['date_begin']); + let end = this.stringToDate(event['date_end']); + let duration = 0; + if (start !== undefined && start !== null && end !== undefined && end !== null) + duration = end - start; + return duration; + } + + /** + * Get events starting after the limit + * + * @param events + * @param limit + * @return {Array} + */ + getEventsAfterLimit(events: Object, limit: Date): Array { + let validEvents = []; + for (let event of events) { + let startDate = this.stringToDate(event['date_begin']); + if (startDate !== undefined && startDate !== null && startDate >= limit) { + validEvents.push(event); + } + } + return validEvents; + } + + /** + * Get the event with the longest duration in the given array. + * If all events have the same duration, return the first in the array. + * @param events + */ + getLongestEvent(events: Array): Object { + let longestEvent = events[0]; + let longestTime = 0; + for (let event of events) { + let time = this.getEventDuration(event); + if (time > longestTime) { + longestTime = time; + longestEvent = event; + } + } + return longestEvent; + } + + /** + * Get events that have not yet ended/started + * + * @param events + */ + getFutureEvents(events: Array): Array { + let validEvents = []; + let now = new Date(); + for (let event of events) { + let startDate = this.stringToDate(event['date_begin']); + let endDate = this.stringToDate(event['date_end']); + if (startDate !== undefined && startDate !== null) { + if (startDate > now) + validEvents.push(event); + else if (endDate !== undefined && endDate !== null) { + if (endDate > now) + validEvents.push(event); } } } + return validEvents; + } + + /** + * + * + * @param events + * @return {Object} + */ + getDisplayEvent(events: Array): Object { + let displayEvent = undefined; + if (events.length > 1) { + let eventsAfterLimit = this.getEventsAfterLimit(events, this.getTodayEventTimeLimit()); + if (eventsAfterLimit.length > 0) { + if (eventsAfterLimit.length === 1) + displayEvent = eventsAfterLimit[0]; + else + displayEvent = this.getLongestEvent(events); + } else { + displayEvent = this.getLongestEvent(events); + } + } else if (events.length === 1) { + displayEvent = events[0]; + } return displayEvent; } - getEventDisplayData(event: Object): Object { - let date = ''; - if (event['date_begin'].split(' ').length > 2) { - date = event['date_begin'].split(' ')[1]; - date = date.split(':')[0] + ':' + date.split(':')[1]; - } - return { - logo: event['logo'], - title: event['title'], - date: date, - description: event['description'], - } + padStr(i: number) { + return (i < 10) ? "0" + i : "" + i; + } + + getFormattedEventTime(event: Object): string { + let formattedStr = ''; + let startDate = this.stringToDate(event['date_begin']); + let endDate = this.stringToDate(event['date_end']); + if (startDate !== undefined && startDate !== null && endDate !== undefined && endDate !== null) + formattedStr = this.padStr(startDate.getHours()) + ':' + this.padStr(startDate.getMinutes()) + + ' - ' + this.padStr(endDate.getHours()) + ':' + this.padStr(endDate.getMinutes()); + else if (startDate !== undefined && startDate !== null) + formattedStr = this.padStr(startDate.getHours()) + ':' + this.padStr(startDate.getMinutes()); + return formattedStr } @@ -201,36 +310,43 @@ export default class HomeScreen extends FetchedDataSectionList { let title = i18n.t('homeScreen.dashboard.todayEventsTitle'); let isAvailable = content.length > 0; let subtitle = ''; + let futureEvents = this.getFutureEvents(content); if (isAvailable) { subtitle = - {content.length} - {i18n.t('homeScreen.dashboard.todayEventsSubtitle')} + {futureEvents.length} + + { + futureEvents.length > 1 ? + i18n.t('homeScreen.dashboard.todayEventsSubtitlePlural') : + i18n.t('homeScreen.dashboard.todayEventsSubtitle') + } + ; } else subtitle = i18n.t('homeScreen.dashboard.todayEventsSubtitleNA'); let clickAction = () => this.props.navigation.navigate('Planning'); - let displayEvent = this.getDisplayEvent(content); + let displayEvent = this.getDisplayEvent(futureEvents); return ( @@ -265,7 +381,8 @@ export default class HomeScreen extends FetchedDataSectionList { {displayEvent['logo'] !== '' && displayEvent['logo'] !== null ? @@ -273,7 +390,7 @@ export default class HomeScreen extends FetchedDataSectionList { } {displayEvent['title']} - {displayEvent['date']} + {this.getFormattedEventTime(displayEvent)} @@ -282,7 +399,7 @@ export default class HomeScreen extends FetchedDataSectionList { backgroundColor: 'transparent', }}> 50 ? 70 : 20, overflow: 'hidden', }}> " + displayEvent['description'] + ""} @@ -301,7 +418,7 @@ export default class HomeScreen extends FetchedDataSectionList { position: 'absolute', width: '100%', height: 60, - bottom: 0 + bottom: 0, }}> @@ -398,7 +515,13 @@ export default class HomeScreen extends FetchedDataSectionList { proximoSubtitle = {proximoData} - {i18n.t('homeScreen.dashboard.proximoSubtitle')} + + { + proximoData > 1 ? + i18n.t('homeScreen.dashboard.proximoSubtitlePlural') : + i18n.t('homeScreen.dashboard.proximoSubtitle') + } + ; } else proximoSubtitle = i18n.t('homeScreen.dashboard.proximoSubtitleNA'); @@ -434,6 +557,14 @@ export default class HomeScreen extends FetchedDataSectionList { let title = i18n.t('homeScreen.dashboard.proxiwashTitle'); let isAvailable = parseInt(content['dryers']) > 0 || parseInt(content['washers']) > 0; let subtitle; + let dryerColor = parseInt(content['dryers']) > 0 ? + ThemeManager.getCurrentThemeVariables().textColor : + ThemeManager.getCurrentThemeVariables().listNoteColor; + let washerColor = parseInt(content['washers']) > 0 ? + ThemeManager.getCurrentThemeVariables().textColor : + ThemeManager.getCurrentThemeVariables().listNoteColor; + let availableDryers = content['dryers']; + let availableWashers = content['washers']; if (isAvailable) { subtitle = @@ -441,24 +572,32 @@ export default class HomeScreen extends FetchedDataSectionList { fontWeight: parseInt(content['dryers']) > 0 ? 'bold' : 'normal', - color: parseInt(content['dryers']) > 0 ? - ThemeManager.getCurrentThemeVariables().textColor : - ThemeManager.getCurrentThemeVariables().listNoteColor + color: dryerColor }}> - {content['dryers']} + {availableDryers} + + + { + availableDryers > 1 ? + i18n.t('homeScreen.dashboard.proxiwashSubtitle1Plural') : + i18n.t('homeScreen.dashboard.proxiwashSubtitle1') + } - {i18n.t('homeScreen.dashboard.proxiwashSubtitle1')} 0 ? 'bold' : 'normal', - color: parseInt(content['washers']) > 0 ? - ThemeManager.getCurrentThemeVariables().textColor : - ThemeManager.getCurrentThemeVariables().listNoteColor + color: washerColor }}> - {content['washers']} + {availableWashers} + + + { + availableWashers > 1 ? + i18n.t('homeScreen.dashboard.proxiwashSubtitle2Plural') : + i18n.t('homeScreen.dashboard.proxiwashSubtitle2') + } - {i18n.t('homeScreen.dashboard.proxiwashSubtitle2')} ; } else subtitle = i18n.t('homeScreen.dashboard.proxiwashSubtitleNA'); @@ -468,18 +607,17 @@ export default class HomeScreen extends FetchedDataSectionList { flex: 0, marginLeft: 10, marginRight: 10, - borderRadius: 50, - backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg + borderRadius: 20, + backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg, + overflow: 'hidden', }}> diff --git a/screens/Proxiwash/ProxiwashScreen.js b/screens/Proxiwash/ProxiwashScreen.js index 4162118..310ed70 100644 --- a/screens/Proxiwash/ProxiwashScreen.js +++ b/screens/Proxiwash/ProxiwashScreen.js @@ -28,6 +28,7 @@ let modalStateStrings = {}; let stateIcons = {}; let stateColors = {}; +const REFRESH_TIME = 1000 * 10; // Refresh every 10 seconds /** * Class defining the app's proxiwash screen. This screen shows information about washing machines and @@ -35,13 +36,11 @@ let stateColors = {}; */ export default class ProxiwashScreen extends FetchedDataSectionList { - refreshInterval: IntervalID; - /** * Creates machine state parameters using current theme and translations */ constructor() { - super(DATA_URL, 1000 * 30); // Refresh every half minute + super(DATA_URL, REFRESH_TIME); let colors = ThemeManager.getCurrentThemeVariables(); stateColors[MACHINE_STATES.TERMINE] = colors.proxiwashFinishedColor; stateColors[MACHINE_STATES.DISPONIBLE] = colors.proxiwashReadyColor; diff --git a/translations/en.json b/translations/en.json index 671781b..9fe3a73 100644 --- a/translations/en.json +++ b/translations/en.json @@ -74,14 +74,18 @@ "dashboard": { "todayEventsTitle": "Today's events", "todayEventsSubtitleNA": "No events today", - "todayEventsSubtitle": " events today", + "todayEventsSubtitle": " event coming today", + "todayEventsSubtitlePlural": " events coming today", "proximoTitle": "Proximo", "proximoSubtitleNA": "No articles available", - "proximoSubtitle": " articles available", + "proximoSubtitle": " article available", + "proximoSubtitlePlural": " articles available", "proxiwashTitle": "Available machines", "proxiwashSubtitleNA": "No machines available", - "proxiwashSubtitle1": " dryers and ", - "proxiwashSubtitle2": " washers", + "proxiwashSubtitle1": " dryer and ", + "proxiwashSubtitle1Plural": " dryers and ", + "proxiwashSubtitle2": " washer", + "proxiwashSubtitle2Plural": " washers", "menuTitle": "Today's menu", "menuSubtitleNA": "No menu available", "menuSubtitle": "Click here to see the menu" diff --git a/translations/fr.json b/translations/fr.json index 87f6dd0..290abec 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -74,14 +74,18 @@ "dashboard": { "todayEventsTitle": "Événements aujourd'hui", "todayEventsSubtitleNA": "Pas d'événements", - "todayEventsSubtitle": " événements aujourd'hui", + "todayEventsSubtitle": " événement aujourd'hui", + "todayEventsSubtitlePlural": " événements aujourd'hui", "proximoTitle": "Proximo", "proximoSubtitleNA": "pas d'article en vente", - "proximoSubtitle": " articles disponibles", + "proximoSubtitle": " article disponible", + "proximoSubtitlePlural": " articles disponibles", "proxiwashTitle": "Machines disponibles", "proxiwashSubtitleNA": "Pas de machine disponible", "proxiwashSubtitle1": " sèches linges et ", + "proxiwashSubtitle1Plural": " sèche linge et ", "proxiwashSubtitle2": " laves linges", + "proxiwashSubtitle2Plural": " lave linge", "menuTitle": "Menu d'aujourd'hui", "menuSubtitleNA": "Pas de menu disponible", "menuSubtitle": "Cliquez ici pour voir le menu"