From 3d9bfdea4c4275a17a1c2fa21e287447c0a070d7 Mon Sep 17 00:00:00 2001 From: Arnaud Vergnet Date: Sun, 2 Aug 2020 19:52:19 +0200 Subject: [PATCH] Improve vote screen to match linter --- src/screens/Amicale/VoteScreen.js | 624 ++++++++++++++++-------------- 1 file changed, 330 insertions(+), 294 deletions(-) diff --git a/src/screens/Amicale/VoteScreen.js b/src/screens/Amicale/VoteScreen.js index 615d54e..817984d 100644 --- a/src/screens/Amicale/VoteScreen.js +++ b/src/screens/Amicale/VoteScreen.js @@ -1,46 +1,47 @@ // @flow import * as React from 'react'; -import {RefreshControl, View} from "react-native"; -import AuthenticatedScreen from "../../components/Amicale/AuthenticatedScreen"; -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 {StackNavigationProp} from "@react-navigation/stack"; -import i18n from "i18n-js"; -import {MASCOT_STYLE} from "../../components/Mascot/Mascot"; -import MascotPopup from "../../components/Mascot/MascotPopup"; -import AsyncStorageManager from "../../managers/AsyncStorageManager"; -import {Button} from "react-native-paper"; -import VoteNotAvailable from "../../components/Amicale/Vote/VoteNotAvailable"; -import CollapsibleFlatList from "../../components/Collapsible/CollapsibleFlatList"; +import {RefreshControl, View} from 'react-native'; +import {StackNavigationProp} from '@react-navigation/stack'; +import i18n from 'i18n-js'; +import {Button} from 'react-native-paper'; +import AuthenticatedScreen from '../../components/Amicale/AuthenticatedScreen'; +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 CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatList'; +import type {ApiGenericDataType} from '../../utils/WebData'; -export type team = { - id: number, - name: string, - votes: number, -} - -type teamResponse = { - has_voted: boolean, - teams: Array, +export type VoteTeamType = { + id: number, + name: string, + votes: number, }; -type stringVoteDates = { - date_begin: string, - date_end: string, - date_result_begin: string, - date_result_end: string, -} +type TeamResponseType = { + has_voted: boolean, + teams: Array, +}; -type objectVoteDates = { - date_begin: Date, - date_end: Date, - date_result_begin: Date, - date_result_end: Date, -} +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, +}; // const FAKE_DATE = { // "date_begin": "2020-08-19 15:50", @@ -92,287 +93,322 @@ type objectVoteDates = { const MIN_REFRESH_TIME = 5 * 1000; -type Props = { - navigation: StackNavigationProp -} +type PropsType = { + navigation: StackNavigationProp, +}; -type State = { - hasVoted: boolean, - mascotDialogVisible: boolean, -} +type StateType = { + hasVoted: boolean, + mascotDialogVisible: boolean, +}; /** * Screen displaying vote information and controls */ -export default class VoteScreen extends React.Component { +export default class VoteScreen extends React.Component { + teams: Array; - state = { - hasVoted: false, - mascotDialogVisible: AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.voteShowBanner.key), + hasVoted: boolean; + + datesString: null | VoteDatesStringType; + + dates: null | VoteDatesObjectType; + + today: Date; + + mainFlatListData: Array<{key: string}>; + + lastRefresh: Date | null; + + authRef: {current: null | AuthenticatedScreen}; + + constructor() { + super(); + this.state = { + hasVoted: false, + mascotDialogVisible: AsyncStorageManager.getBool( + AsyncStorageManager.PREFERENCES.voteShowBanner.key, + ), }; + this.hasVoted = false; + this.today = new Date(); + this.authRef = React.createRef(); + this.lastRefresh = null; + this.mainFlatListData = [{key: 'main'}, {key: 'info'}]; + } - teams: Array; - hasVoted: boolean; - datesString: null | stringVoteDates; - dates: null | objectVoteDates; + /** + * 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; + } - today: Date; + getMainRenderItem = ({item}: {item: {key: string}}): React.Node => { + if (item.key === 'info') + return ( + + + + ); + return this.getContent(); + }; - mainFlatListData: Array<{ key: string }>; - lastRefresh: Date | null; + getScreen = (data: Array): React.Node => { + const {state} = this; + // data[0] = FAKE_TEAMS2; + // data[1] = FAKE_DATE; + this.lastRefresh = new Date(); - authRef: { current: null | AuthenticatedScreen }; + const teams: TeamResponseType | null = data[0]; + const dateStrings: VoteDatesStringType | null = data[1]; - constructor() { - super(); - this.hasVoted = false; - this.today = new Date(); - this.authRef = React.createRef(); - this.lastRefresh = null; - this.mainFlatListData = [ - {key: 'main'}, - {key: 'info'}, - ] + if (dateStrings != null && dateStrings.date_begin == null) + this.datesString = null; + else this.datesString = dateStrings; + + if (teams != null) { + this.teams = teams.teams; + this.hasVoted = teams.has_voted; } - /** - * Reloads vote data if last refresh delta is smaller than the minimum refresh time - */ - reloadData = () => { - let canRefresh; - const lastRefresh = this.lastRefresh; - if (lastRefresh != null) - canRefresh = (new Date().getTime() - lastRefresh.getTime()) > MIN_REFRESH_TIME; - else - canRefresh = true; - if (canRefresh && this.authRef.current != null) - this.authRef.current.reload() - }; - - /** - * 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 = null; - } else - this.dates = null; - } - - /** - * 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 : ""; - } else - return dateString; - } - - isVoteRunning() { - return this.dates != null && this.today > this.dates.date_begin && this.today < this.dates.date_end; - } - - isVoteStarted() { - return this.dates != null && this.today > this.dates.date_begin; - } - - isResultRunning() { - return this.dates != null && this.today > this.dates.date_result_begin && this.today < this.dates.date_result_end; - } - - isResultStarted() { - return this.dates != null && this.today > this.dates.date_result_begin; - } - - mainRenderItem = ({item}: { item: { key: string } }) => { - if (item.key === 'info') - return ( - - - - ); - else - return this.getContent(); - }; - - getScreen = (data: Array<{ [key: string]: any } | null>) => { - // data[0] = FAKE_TEAMS2; - // data[1] = FAKE_DATE; - this.lastRefresh = new Date(); - - const teams: teamResponse | null = data[0]; - const dateStrings: stringVoteDates | null = data[1]; - - if (dateStrings != null && dateStrings.date_begin == null) - this.datesString = null; - else - this.datesString = dateStrings; - - if (teams != null) { - this.teams = teams.teams; - this.hasVoted = teams.has_voted; + this.generateDateObject(); + return ( + } + extraData={state.hasVoted.toString()} + renderItem={this.getMainRenderItem} + /> + ); + }; - this.generateDateObject(); - return ( - - } - extraData={this.state.hasVoted.toString()} - renderItem={this.mainRenderItem} - /> - ); - }; + getContent(): React.Node { + 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 ; + } - getContent() { - if (!this.isVoteStarted()) - return this.getTeaseVoteCard(); - else if (this.isVoteRunning() && (!this.hasVoted && !this.state.hasVoted)) - return this.getVoteCard(); - else if (!this.isResultStarted()) - return this.getWaitVoteCard(); - else if (this.isResultRunning()) - return this.getVoteResultCard(); - else - return ; - } + onVoteSuccess = (): void => this.setState({hasVoted: true}); - onVoteSuccess = () => this.setState({hasVoted: true}); + /** + * The user has not voted yet, and the votes are open + */ + getVoteCard(): React.Node { + return ( + + ); + } - /** - * The user has not voted yet, and the votes are open - */ - getVoteCard() { - return ; - } + /** + * Votes have ended, results can be displayed + */ + getVoteResultCard(): React.Node { + if (this.dates != null && this.datesString != null) + return ( + + ); + return ; + } - /** - * Votes have ended, results can be displayed - */ - getVoteResultCard() { - if (this.dates != null && this.datesString != null) - return ; - else - return ; - } + /** + * Vote will open shortly + */ + getTeaseVoteCard(): React.Node { + if (this.dates != null && this.datesString != null) + return ( + + ); + return ; + } - /** - * Vote will open shortly - */ - getTeaseVoteCard() { - if (this.dates != null && this.datesString != null) - return ; - else - return ; - } + /** + * Votes have ended, or user has voted waiting for results + */ + getWaitVoteCard(): React.Node { + 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 ( + + ); + } - /** - * Votes have ended, or user has voted waiting for results - */ - getWaitVoteCard() { - 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 ; - } + /** + * Reloads vote data if last refresh delta is smaller than the minimum refresh time + */ + reloadData = () => { + let canRefresh; + const {lastRefresh} = this; + if (lastRefresh != null) + canRefresh = + new Date().getTime() - lastRefresh.getTime() > MIN_REFRESH_TIME; + else canRefresh = true; + if (canRefresh && this.authRef.current != null) + this.authRef.current.reload(); + }; - showMascotDialog = () => { - this.setState({mascotDialogVisible: true}) - }; + showMascotDialog = () => { + this.setState({mascotDialogVisible: true}); + }; - hideMascotDialog = () => { - AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.voteShowBanner.key, false); - this.setState({mascotDialogVisible: false}) - }; + hideMascotDialog = () => { + AsyncStorageManager.set( + AsyncStorageManager.PREFERENCES.voteShowBanner.key, + false, + ); + this.setState({mascotDialogVisible: false}); + }; - /** - * Renders the authenticated screen. - * - * Teams and dates are not mandatory to allow showing the information box even if api requests fail - * - * @returns {*} - */ - render() { - return ( - - - - - ); - } + 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 = null; + } else this.dates = null; + } + + /** + * Renders the authenticated screen. + * + * Teams and dates are not mandatory to allow showing the information box even if api requests fail + * + * @returns {*} + */ + render(): React.Node { + const {props, state} = this; + return ( + + + + + ); + } }