/* * Copyright (c) 2019 - 2020 Arnaud Vergnet. * * This file is part of Campus INSAT. * * Campus INSAT is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Campus INSAT is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Campus INSAT. If not, see . */ import * as React from 'react'; import {BackHandler, View} from 'react-native'; import i18n from 'i18n-js'; import {Agenda, LocaleConfig} from 'react-native-calendars'; import {Avatar, Divider, List} from 'react-native-paper'; import {StackNavigationProp} from '@react-navigation/stack'; import {readData} from '../../utils/WebData'; import { generateEventAgenda, getCurrentDateString, getDateOnlyString, getTimeOnlyString, PlanningEventType, } from '../../utils/Planning'; import CustomAgenda from '../../components/Overrides/CustomAgenda'; import {MASCOT_STYLE} from '../../components/Mascot/Mascot'; import MascotPopup from '../../components/Mascot/MascotPopup'; import AsyncStorageManager from '../../managers/AsyncStorageManager'; LocaleConfig.locales.fr = { monthNames: [ 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre', ], monthNamesShort: [ 'Janv.', 'Févr.', 'Mars', 'Avril', 'Mai', 'Juin', 'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.', ], dayNames: [ 'Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', ], dayNamesShort: ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'], }; type PropsType = { navigation: StackNavigationProp; }; type StateType = { refreshing: boolean; agendaItems: {[key: string]: Array}; calendarShowing: boolean; }; const FETCH_URL = 'https://www.amicale-insat.fr/api/event/list'; const AGENDA_MONTH_SPAN = 3; /** * Class defining the app's planning screen */ class PlanningScreen extends React.Component { agendaRef: null | Agenda; lastRefresh: Date | null; minTimeBetweenRefresh = 60; currentDate: string | null; constructor(props: PropsType) { super(props); if (i18n.currentLocale().startsWith('fr')) { LocaleConfig.defaultLocale = 'fr'; } this.agendaRef = null; this.currentDate = getDateOnlyString(getCurrentDateString()); this.lastRefresh = null; this.state = { refreshing: false, agendaItems: {}, calendarShowing: false, }; } /** * Captures focus and blur events to hook on android back button */ componentDidMount() { const {navigation} = this.props; this.onRefresh(); navigation.addListener('focus', () => { BackHandler.addEventListener( 'hardwareBackPress', this.onBackButtonPressAndroid, ); }); navigation.addListener('blur', () => { BackHandler.removeEventListener( 'hardwareBackPress', this.onBackButtonPressAndroid, ); }); } /** * Overrides default android back button behaviour to close the calendar if it was open. * * @return {boolean} */ onBackButtonPressAndroid = (): boolean => { const {calendarShowing} = this.state; if (calendarShowing && this.agendaRef != null) { // @ts-ignore this.agendaRef.chooseDay(this.agendaRef.state.selectedDay); return true; } return false; }; /** * Refreshes data and shows an animation while doing it */ onRefresh = () => { let canRefresh; if (this.lastRefresh) { canRefresh = (new Date().getTime() - this.lastRefresh.getTime()) / 1000 > this.minTimeBetweenRefresh; } else { canRefresh = true; } if (canRefresh) { this.setState({refreshing: true}); readData(FETCH_URL) .then((fetchedData: Array) => { this.setState({ refreshing: false, agendaItems: generateEventAgenda(fetchedData, AGENDA_MONTH_SPAN), }); this.lastRefresh = new Date(); }) .catch(() => { this.setState({ refreshing: false, }); }); } }; /** * Callback used when receiving the agenda ref * * @param ref */ onAgendaRef = (ref: Agenda) => { this.agendaRef = ref; }; /** * Callback used when a button is pressed to toggle the calendar * * @param isCalendarOpened True is the calendar is already open, false otherwise */ onCalendarToggled = (isCalendarOpened: boolean) => { this.setState({calendarShowing: isCalendarOpened}); }; /** * Gets an event render item * * @param item The current event to render * @return {*} */ getRenderItem = (item: PlanningEventType) => { const {navigation} = this.props; const onPress = () => { navigation.navigate('planning-information', { data: item, }); }; const logo = item.logo; if (logo) { return ( ( )} onPress={onPress} /> ); } return ( ); }; /** * Gets an empty render item for an empty date * * @return {*} */ getRenderEmptyDate = () => ; render() { const {state, props} = this; return ( r1.id !== r2.id } /> ); } } export default PlanningScreen;