/* * 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 React, { useRef, useState } 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 VoteNotAvailable from '../../components/Amicale/Vote/VoteNotAvailable'; import GENERAL_STYLES from '../../constants/Styles'; import WebSectionList, { SectionListDataType, } from '../../components/Screens/WebSectionList'; import { useAuthenticatedRequest } from '../../context/loginContext'; 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; }; type FlatlistType = { teams: Array; hasVoted: boolean; datesString?: VoteDatesStringType; dates?: VoteDatesObjectType; }; // 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, // }, // ], // }; const styles = StyleSheet.create({ button: { marginLeft: 'auto', marginRight: 'auto', marginTop: 20, }, }); /** * Screen displaying vote information and controls */ export default function VoteScreen() { const [hasVoted, setHasVoted] = useState(false); const [mascotDialogVisible, setMascotDialogVisible] = useState< undefined | boolean >(undefined); const datesRequest = useAuthenticatedRequest('elections/dates'); const teamsRequest = useAuthenticatedRequest('elections/teams'); const today = new Date(); const refresh = useRef<() => void | undefined>(); /** * 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} */ const getDateString = (date: Date, dateString: string) => { if (today.getDate() === date.getDate()) { const str = getTimeOnlyString(dateString); return str != null ? str : ''; } return dateString; }; const getMainRenderItem = ({ item, }: { item: { key: string; data?: FlatlistType }; }) => { if (item.key === 'info') { return ( ); } if (item.data) { return getContent(item.data); } else { return ; } }; const createDataset = ( data: ResponseType | undefined, _loading: boolean, _lastRefreshDate: Date | undefined, refreshData: () => void ) => { // data[0] = FAKE_TEAMS2; // data[1] = FAKE_DATE; const mainFlatListData: SectionListDataType<{ key: string; data?: FlatlistType; }> = [ { title: '', data: [{ key: 'main' }, { key: 'info' }], }, ]; refresh.current = refreshData; if (data) { const { teams, dates } = data; const flatlistData: FlatlistType = { teams: [], hasVoted: false, }; if (dates && dates.date_begin != null) { flatlistData.datesString = dates; } if (teams) { flatlistData.teams = teams.teams; flatlistData.hasVoted = teams.has_voted; } flatlistData.dates = generateDateObject(flatlistData.datesString); } return mainFlatListData; }; const getContent = (data: FlatlistType) => { const { dates } = data; if (!isVoteStarted(dates)) { return getTeaseVoteCard(data); } if (isVoteRunning(dates) && !data.hasVoted && !hasVoted) { return getVoteCard(data); } if (!isResultStarted(dates)) { return getWaitVoteCard(data); } if (isResultRunning(dates)) { return getVoteResultCard(data); } return ; }; const onVoteSuccess = () => setHasVoted(true); /** * The user has not voted yet, and the votes are open */ const getVoteCard = (data: FlatlistType) => { return ( { if (refresh.current) { refresh.current(); } }} /> ); }; /** * Votes have ended, results can be displayed */ const getVoteResultCard = (data: FlatlistType) => { if (data.dates != null && data.datesString != null) { return ( ); } return ; }; /** * Vote will open shortly */ const getTeaseVoteCard = (data: FlatlistType) => { if (data.dates != null && data.datesString != null) { return ( ); } return ; }; /** * Votes have ended, or user has voted waiting for results */ const getWaitVoteCard = (data: FlatlistType) => { let startDate = null; if ( data.dates != null && data.datesString != null && data.dates.date_result_begin != null ) { startDate = getDateString( data.dates.date_result_begin, data.datesString.date_result_begin ); } return ( ); }; const showMascotDialog = () => setMascotDialogVisible(true); const hideMascotDialog = () => setMascotDialogVisible(false); const isVoteStarted = (dates?: VoteDatesObjectType) => { return dates != null && today > dates.date_begin; }; const isResultRunning = (dates?: VoteDatesObjectType) => { return ( dates != null && today > dates.date_result_begin && today < dates.date_result_end ); }; const isResultStarted = (dates?: VoteDatesObjectType) => { return dates != null && today > dates.date_result_begin; }; const isVoteRunning = (dates?: VoteDatesObjectType) => { return dates != null && today > dates.date_begin && today < dates.date_end; }; /** * Generates the objects containing string and Date representations of key vote dates */ const generateDateObject = ( strings?: VoteDatesStringType ): VoteDatesObjectType | undefined => { if (strings) { 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 ) { return { date_begin: dateBegin, date_end: dateEnd, date_result_begin: dateResultBegin, date_result_end: dateResultEnd, }; } else { return undefined; } } else { return undefined; } }; const request = () => { return new Promise((resolve: (data: ResponseType) => void) => { datesRequest() .then((datesData) => { teamsRequest() .then((teamsData) => { resolve({ dates: datesData, teams: teamsData, }); }) .catch(() => resolve({ dates: datesData, }) ); }) .catch(() => resolve({})); }); }; return ( ); }