/* * 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 { StyleSheet, View } from 'react-native'; import i18n from 'i18n-js'; import { Button } from 'react-native-paper'; import { getTimeOnlyString, stringToDate } from '../../utils/Planning'; import VoteTease from '../../components/Amicale/Vote/VoteTease'; import VoteSelect from '../../components/Amicale/Vote/VoteSelect'; import VoteResults from '../../components/Amicale/Vote/VoteResults'; import VoteWait from '../../components/Amicale/Vote/VoteWait'; import { MASCOT_STYLE } from '../../components/Mascot/Mascot'; import MascotPopup from '../../components/Mascot/MascotPopup'; import AsyncStorageManager from '../../managers/AsyncStorageManager'; import VoteNotAvailable from '../../components/Amicale/Vote/VoteNotAvailable'; import GENERAL_STYLES from '../../constants/Styles'; import ConnectionManager from '../../managers/ConnectionManager'; import WebSectionList, { SectionListDataType, } from '../../components/Screens/WebSectionList'; export type VoteTeamType = { id: number; name: string; votes: number; }; type TeamResponseType = { has_voted: boolean; teams: Array; }; type VoteDatesStringType = { date_begin: string; date_end: string; date_result_begin: string; date_result_end: string; }; type VoteDatesObjectType = { date_begin: Date; date_end: Date; date_result_begin: Date; date_result_end: Date; }; type ResponseType = { teams?: TeamResponseType; dates?: VoteDatesStringType; }; // const FAKE_DATE = { // "date_begin": "2020-08-19 15:50", // "date_end": "2020-08-19 15:50", // "date_result_begin": "2020-08-19 19:50", // "date_result_end": "2020-08-19 22:50", // }; // // const FAKE_DATE2 = { // "date_begin": null, // "date_end": null, // "date_result_begin": null, // "date_result_end": null, // }; // // const FAKE_TEAMS = { // has_voted: false, // teams: [ // { // id: 1, // name: "TEST TEAM1", // }, // { // id: 2, // name: "TEST TEAM2", // }, // ], // }; // const FAKE_TEAMS2 = { // has_voted: false, // teams: [ // { // id: 1, // name: "TEST TEAM1", // votes: 9, // }, // { // id: 2, // name: "TEST TEAM2", // votes: 9, // }, // { // id: 3, // name: "TEST TEAM3", // votes: 5, // }, // ], // }; type PropsType = {}; type StateType = { hasVoted: boolean; mascotDialogVisible: boolean; }; const styles = StyleSheet.create({ button: { marginLeft: 'auto', marginRight: 'auto', marginTop: 20, }, }); /** * Screen displaying vote information and controls */ export default class VoteScreen extends React.Component { teams: Array; hasVoted: boolean; datesString: undefined | VoteDatesStringType; dates: undefined | VoteDatesObjectType; today: Date; mainFlatListData: SectionListDataType<{ key: string }>; refreshData: () => void; constructor(props: PropsType) { super(props); this.teams = []; this.datesString = undefined; this.dates = undefined; this.state = { hasVoted: false, mascotDialogVisible: AsyncStorageManager.getBool( AsyncStorageManager.PREFERENCES.voteShowMascot.key ), }; this.hasVoted = false; this.today = new Date(); this.refreshData = () => undefined; this.mainFlatListData = [ { title: '', data: [{ key: 'main' }, { key: 'info' }] }, ]; } /** * Gets the string representation of the given date. * * If the given date is the same day as today, only return the tile. * Otherwise, return the full date. * * @param date The Date object representation of the wanted date * @param dateString The string representation of the wanted date * @returns {string} */ getDateString(date: Date, dateString: string): string { if (this.today.getDate() === date.getDate()) { const str = getTimeOnlyString(dateString); return str != null ? str : ''; } return dateString; } getMainRenderItem = ({ item }: { item: { key: string } }) => { if (item.key === 'info') { return ( ); } return this.getContent(); }; createDataset = ( data: ResponseType | undefined, _loading: boolean, _lastRefreshDate: Date | undefined, refreshData: () => void ) => { // data[0] = FAKE_TEAMS2; // data[1] = FAKE_DATE; this.refreshData = refreshData; if (data) { const { teams, dates } = data; if (dates && dates.date_begin == null) { this.datesString = undefined; } else { this.datesString = dates; } if (teams) { this.teams = teams.teams; this.hasVoted = teams.has_voted; } this.generateDateObject(); } return this.mainFlatListData; }; getContent() { const { state } = this; if (!this.isVoteStarted()) { return this.getTeaseVoteCard(); } if (this.isVoteRunning() && !this.hasVoted && !state.hasVoted) { return this.getVoteCard(); } if (!this.isResultStarted()) { return this.getWaitVoteCard(); } if (this.isResultRunning()) { return this.getVoteResultCard(); } return ; } onVoteSuccess = (): void => this.setState({ hasVoted: true }); /** * The user has not voted yet, and the votes are open */ getVoteCard() { return ( ); } /** * Votes have ended, results can be displayed */ getVoteResultCard() { if (this.dates != null && this.datesString != null) { return ( ); } return ; } /** * Vote will open shortly */ getTeaseVoteCard() { if (this.dates != null && this.datesString != null) { return ( ); } return ; } /** * Votes have ended, or user has voted waiting for results */ getWaitVoteCard() { const { state } = this; let startDate = null; if ( this.dates != null && this.datesString != null && this.dates.date_result_begin != null ) { startDate = this.getDateString( this.dates.date_result_begin, this.datesString.date_result_begin ); } return ( ); } showMascotDialog = () => { this.setState({ mascotDialogVisible: true }); }; hideMascotDialog = () => { AsyncStorageManager.set( AsyncStorageManager.PREFERENCES.voteShowMascot.key, false ); this.setState({ mascotDialogVisible: false }); }; isVoteStarted(): boolean { return this.dates != null && this.today > this.dates.date_begin; } isResultRunning(): boolean { return ( this.dates != null && this.today > this.dates.date_result_begin && this.today < this.dates.date_result_end ); } isResultStarted(): boolean { return this.dates != null && this.today > this.dates.date_result_begin; } isVoteRunning(): boolean { return ( this.dates != null && this.today > this.dates.date_begin && this.today < this.dates.date_end ); } /** * Generates the objects containing string and Date representations of key vote dates */ generateDateObject() { const strings = this.datesString; if (strings != null) { const dateBegin = stringToDate(strings.date_begin); const dateEnd = stringToDate(strings.date_end); const dateResultBegin = stringToDate(strings.date_result_begin); const dateResultEnd = stringToDate(strings.date_result_end); if ( dateBegin != null && dateEnd != null && dateResultBegin != null && dateResultEnd != null ) { this.dates = { date_begin: dateBegin, date_end: dateEnd, date_result_begin: dateResultBegin, date_result_end: dateResultEnd, }; } else { this.dates = undefined; } } else { this.dates = undefined; } } request = () => { return new Promise((resolve: (data: ResponseType) => void) => { ConnectionManager.getInstance() .authenticatedRequest('elections/dates') .then((datesData) => { ConnectionManager.getInstance() .authenticatedRequest('elections/teams') .then((teamsData) => { resolve({ dates: datesData, teams: teamsData, }); }) .catch(() => resolve({ dates: datesData, }) ); }) .catch(() => resolve({})); }); }; /** * Renders the authenticated screen. * * Teams and dates are not mandatory to allow showing the information box even if api requests fail * * @returns {*} */ render() { const { state } = this; return ( ); } }