forked from vergnet/application-amicale
Moved vote cards in own component files
This commit is contained in:
parent
34594f82d9
commit
9fc3620044
8 changed files with 443 additions and 299 deletions
|
@ -48,7 +48,7 @@ class AuthenticatedScreen extends React.Component<Props, State> {
|
|||
this.setState({loading: true});
|
||||
if (this.connectionManager.isLoggedIn()) {
|
||||
for (let i = 0; i < this.props.links.length; i++) {
|
||||
this.connectionManager.authenticatedRequest(this.props.links[i].link)
|
||||
this.connectionManager.authenticatedRequest(this.props.links[i].link, null, null)
|
||||
.then((data) => {
|
||||
this.onFinishedLoading(data, i, -1);
|
||||
})
|
||||
|
|
104
src/components/Amicale/Vote/VoteResults.js
Normal file
104
src/components/Amicale/Vote/VoteResults.js
Normal file
|
@ -0,0 +1,104 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {Avatar, Card, List, ProgressBar, Subheading, withTheme} from "react-native-paper";
|
||||
import {FlatList, StyleSheet} from "react-native";
|
||||
|
||||
type Props = {
|
||||
teams: Array<Object>,
|
||||
dateEnd: string,
|
||||
}
|
||||
|
||||
class VoteResults extends React.Component<Props> {
|
||||
|
||||
totalVotes: number;
|
||||
winnerId: number;
|
||||
colors: Object;
|
||||
|
||||
constructor(props) {
|
||||
super();
|
||||
this.colors = props.theme.colors;
|
||||
props.teams.sort(this.sortByVotes);
|
||||
this.getTotalVotes(props.teams);
|
||||
this.getWinnerId(props.teams);
|
||||
}
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
sortByVotes = (a: Object, b: Object) => b.votes - a.votes;
|
||||
|
||||
getTotalVotes(teams: Array<Object>) {
|
||||
this.totalVotes = 0;
|
||||
for (let i = 0; i < teams.length; i++) {
|
||||
this.totalVotes += teams[i].votes;
|
||||
}
|
||||
}
|
||||
|
||||
getWinnerId(teams: Array<Object>) {
|
||||
this.winnerId = teams[0].id;
|
||||
}
|
||||
|
||||
voteKeyExtractor = (item: Object) => item.id.toString();
|
||||
|
||||
resultRenderItem = ({item}: Object) => {
|
||||
const isWinner = this.winnerId === item.id;
|
||||
return (
|
||||
<Card style={{
|
||||
marginTop: 10,
|
||||
elevation: isWinner ? 5 : 3,
|
||||
}}>
|
||||
<List.Item
|
||||
title={item.name}
|
||||
description={item.votes + " VOTES"}
|
||||
left={props => isWinner
|
||||
? <List.Icon {...props} icon="trophy" color={this.colors.primary}/>
|
||||
: null}
|
||||
titleStyle={{
|
||||
color: isWinner
|
||||
? this.colors.primary
|
||||
: this.colors.text
|
||||
}}
|
||||
style={{padding: 0}}
|
||||
/>
|
||||
<ProgressBar progress={item.votes / this.totalVotes} color={this.colors.primary}/>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Card style={styles.card}>
|
||||
<Card.Title
|
||||
title={"RESULTS"}
|
||||
subtitle={"AVAILABLE UNTIL " + this.props.dateEnd}
|
||||
left={(props) => <Avatar.Icon
|
||||
{...props}
|
||||
icon={"podium-gold"}
|
||||
/>}
|
||||
/>
|
||||
<Card.Content>
|
||||
<Subheading>TOTAL VOTES : {this.totalVotes}</Subheading>
|
||||
{/*$FlowFixMe*/}
|
||||
<FlatList
|
||||
data={this.props.teams}
|
||||
keyExtractor={this.voteKeyExtractor}
|
||||
renderItem={this.resultRenderItem}
|
||||
/>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
card: {
|
||||
margin: 10,
|
||||
},
|
||||
icon: {
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
});
|
||||
|
||||
export default withTheme(VoteResults);
|
135
src/components/Amicale/Vote/VoteSelect.js
Normal file
135
src/components/Amicale/Vote/VoteSelect.js
Normal file
|
@ -0,0 +1,135 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {Avatar, Button, Card, RadioButton} from "react-native-paper";
|
||||
import {FlatList, StyleSheet, View} from "react-native";
|
||||
import ConnectionManager from "../../../managers/ConnectionManager";
|
||||
import LoadingConfirmDialog from "../../Dialog/LoadingConfirmDialog";
|
||||
import ErrorDialog from "../../Dialog/ErrorDialog";
|
||||
|
||||
type Props = {
|
||||
teams: Array<Object>,
|
||||
onVoteSuccess: Function,
|
||||
onVoteError: Function,
|
||||
}
|
||||
|
||||
type State = {
|
||||
selectedTeam: string,
|
||||
voteDialogVisible: boolean,
|
||||
errorDialogVisible: boolean,
|
||||
currentError: number,
|
||||
}
|
||||
|
||||
|
||||
export default class VoteSelect extends React.PureComponent<Props, State> {
|
||||
|
||||
state = {
|
||||
selectedTeam: "none",
|
||||
voteDialogVisible: false,
|
||||
errorDialogVisible: false,
|
||||
currentError: 0,
|
||||
};
|
||||
|
||||
onVoteSelectionChange = (team: string) => this.setState({selectedTeam: team});
|
||||
|
||||
voteKeyExtractor = (item: Object) => item.id.toString();
|
||||
|
||||
voteRenderItem = ({item}: Object) => <RadioButton.Item label={item.name} value={item.id.toString()}/>;
|
||||
|
||||
showVoteDialog = () => this.setState({voteDialogVisible: true});
|
||||
|
||||
onVoteDialogDismiss = () => this.setState({voteDialogVisible: false,});
|
||||
|
||||
onVoteDialogAccept = async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
ConnectionManager.getInstance().authenticatedRequest(
|
||||
"elections/vote",
|
||||
["vote"],
|
||||
[parseInt(this.state.selectedTeam)])
|
||||
.then(() => {
|
||||
this.onVoteDialogDismiss();
|
||||
this.props.onVoteSuccess();
|
||||
resolve();
|
||||
})
|
||||
.catch((error: number) => {
|
||||
this.onVoteDialogDismiss();
|
||||
this.showErrorDialog(error);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
showErrorDialog = (error: number) => this.setState({
|
||||
errorDialogVisible: true,
|
||||
currentError: error,
|
||||
});
|
||||
|
||||
onErrorDialogDismiss = () => {
|
||||
this.setState({errorDialogVisible: false});
|
||||
this.props.onVoteError();
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<Card style={styles.card}>
|
||||
<Card.Title
|
||||
title={"VOTE OPEN"}
|
||||
subtitle={"VOTE NOW"}
|
||||
left={(props) => <Avatar.Icon
|
||||
{...props}
|
||||
icon={"alert-decagram"}
|
||||
/>}
|
||||
/>
|
||||
<Card.Content>
|
||||
<RadioButton.Group
|
||||
onValueChange={this.onVoteSelectionChange}
|
||||
value={this.state.selectedTeam}
|
||||
>
|
||||
{/*$FlowFixMe*/}
|
||||
<FlatList
|
||||
data={this.props.teams}
|
||||
keyExtractor={this.voteKeyExtractor}
|
||||
extraData={this.state.selectedTeam}
|
||||
renderItem={this.voteRenderItem}
|
||||
/>
|
||||
</RadioButton.Group>
|
||||
</Card.Content>
|
||||
<Card.Actions>
|
||||
<Button
|
||||
icon="send"
|
||||
mode="contained"
|
||||
onPress={this.showVoteDialog}
|
||||
style={{marginLeft: 'auto'}}
|
||||
disabled={this.state.selectedTeam === "none"}
|
||||
>
|
||||
SEND VOTE
|
||||
</Button>
|
||||
</Card.Actions>
|
||||
</Card>
|
||||
<LoadingConfirmDialog
|
||||
visible={this.state.voteDialogVisible}
|
||||
onDismiss={this.onVoteDialogDismiss}
|
||||
onAccept={this.onVoteDialogAccept}
|
||||
title={"VOTE?"}
|
||||
titleLoading={"SENDING VOTE..."}
|
||||
message={"SURE?"}
|
||||
/>
|
||||
<ErrorDialog
|
||||
visible={this.state.errorDialogVisible}
|
||||
onDismiss={this.onErrorDialogDismiss}
|
||||
errorCode={this.state.currentError}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
card: {
|
||||
margin: 10,
|
||||
},
|
||||
icon: {
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
});
|
45
src/components/Amicale/Vote/VoteTease.js
Normal file
45
src/components/Amicale/Vote/VoteTease.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {Avatar, Card, Paragraph} from "react-native-paper";
|
||||
import {StyleSheet} from "react-native";
|
||||
|
||||
type Props = {
|
||||
startDate: string,
|
||||
}
|
||||
|
||||
export default class VoteTease extends React.Component<Props> {
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Card style={styles.card}>
|
||||
<Card.Title
|
||||
title={"VOTE INCOMING"}
|
||||
subtitle={"GET READY"}
|
||||
left={props => <Avatar.Icon
|
||||
{...props}
|
||||
icon="vote"/>}
|
||||
/>
|
||||
<Card.Content>
|
||||
<Paragraph>
|
||||
VOTE STARTS
|
||||
AT {this.props.startDate}
|
||||
</Paragraph>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
card: {
|
||||
margin: 10,
|
||||
},
|
||||
icon: {
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
});
|
54
src/components/Amicale/Vote/VoteTitle.js
Normal file
54
src/components/Amicale/Vote/VoteTitle.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {Avatar, Card, Paragraph} from "react-native-paper";
|
||||
import {StyleSheet} from "react-native";
|
||||
|
||||
const ICON_AMICALE = require('../../../../assets/amicale.png');
|
||||
|
||||
type Props = {}
|
||||
|
||||
export default class VoteTitle extends React.Component<Props> {
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Card style={styles.card}>
|
||||
<Card.Title
|
||||
title={"VOTE"}
|
||||
subtitle={"WHY"}
|
||||
left={(props) => <Avatar.Image
|
||||
{...props}
|
||||
source={ICON_AMICALE}
|
||||
style={styles.icon}
|
||||
/>}
|
||||
/>
|
||||
<Card.Content>
|
||||
<Paragraph>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus rhoncus porttitor
|
||||
suscipit. Quisque hendrerit, quam id vestibulum vestibulum, lorem nisi hendrerit nisi, a
|
||||
eleifend sapien diam ut elit. Curabitur sit amet vulputate lectus. Donec semper cursus sapien
|
||||
vel finibus.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
Sed et venenatis turpis. Fusce malesuada magna urna, sed vehicula sem luctus in. Vivamus
|
||||
faucibus vel eros a ultricies. In sed laoreet ante, luctus mattis tellus. Etiam vitae ipsum
|
||||
sagittis, consequat purus sed, blandit risus.
|
||||
</Paragraph>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
card: {
|
||||
margin: 10,
|
||||
},
|
||||
icon: {
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
});
|
73
src/components/Amicale/Vote/VoteWait.js
Normal file
73
src/components/Amicale/Vote/VoteWait.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {ActivityIndicator, Card, Paragraph, withTheme} from "react-native-paper";
|
||||
import {StyleSheet} from "react-native";
|
||||
|
||||
type Props = {
|
||||
startDate: string | null,
|
||||
justVoted: boolean,
|
||||
hasVoted: boolean,
|
||||
isVoteRunning: boolean,
|
||||
}
|
||||
|
||||
class VoteWait extends React.Component<Props> {
|
||||
|
||||
colors: Object;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.colors = props.theme.colors;
|
||||
}
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Card style={styles.card}>
|
||||
<Card.Title
|
||||
title={this.props.isVoteRunning ? "VOTE SUBMITTED" : "VOTES HAVE ENDED"}
|
||||
subtitle={"WAITING FOR RESULTS"}
|
||||
left={(props) => <ActivityIndicator {...props}/>}
|
||||
/>
|
||||
<Card.Content>
|
||||
{
|
||||
this.props.justVoted
|
||||
? <Paragraph style={{color: this.colors.success}}>
|
||||
VOTE SUBMITTED. THX FOR YOUR PARTICIPATION
|
||||
</Paragraph>
|
||||
: null
|
||||
}
|
||||
{
|
||||
this.props.hasVoted
|
||||
? <Paragraph style={{color: this.colors.success}}>
|
||||
THX FOR THE VOTE
|
||||
</Paragraph>
|
||||
: null
|
||||
}
|
||||
{
|
||||
this.props.startDate !== null
|
||||
? <Paragraph>
|
||||
RESULTS AVAILABLE
|
||||
AT {this.props.startDate}
|
||||
</Paragraph>
|
||||
: <Paragraph>RESULTS AVAILABLE SHORTLY</Paragraph>
|
||||
}
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
card: {
|
||||
margin: 10,
|
||||
},
|
||||
icon: {
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
});
|
||||
|
||||
export default withTheme(VoteWait);
|
|
@ -190,11 +190,11 @@ export default class ConnectionManager {
|
|||
return data;
|
||||
}
|
||||
|
||||
async authenticatedRequest(path: string, keys: Array<string>, values: Array<any>) {
|
||||
async authenticatedRequest(path: string, keys: Array<string>|null, values: Array<any>|null) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.getToken() !== null) {
|
||||
let data = {};
|
||||
if (keys !== undefined && values !== undefined && keys.length === values.length)
|
||||
if (keys !== null && values !== null && keys.length === values.length)
|
||||
data = this.generatePostArguments(keys, values);
|
||||
console.log(data);
|
||||
fetch(API_ENDPOINT + path, {
|
||||
|
|
|
@ -1,32 +1,20 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {FlatList, StyleSheet, View} from "react-native";
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Avatar,
|
||||
Button,
|
||||
Card,
|
||||
List,
|
||||
Paragraph,
|
||||
ProgressBar,
|
||||
RadioButton,
|
||||
Subheading,
|
||||
withTheme
|
||||
} from 'react-native-paper';
|
||||
import {FlatList, View} from "react-native";
|
||||
import AuthenticatedScreen from "../../components/Amicale/AuthenticatedScreen";
|
||||
import {getTimeOnlyString, stringToDate} from "../../utils/Planning";
|
||||
import LoadingConfirmDialog from "../../components/Dialog/LoadingConfirmDialog";
|
||||
import ConnectionManager from "../../managers/ConnectionManager";
|
||||
import ErrorDialog from "../../components/Dialog/ErrorDialog";
|
||||
|
||||
const ICON_AMICALE = require('../../../assets/amicale.png');
|
||||
import VoteTitle from "../../components/Amicale/Vote/VoteTitle";
|
||||
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";
|
||||
|
||||
const FAKE_DATE = {
|
||||
"date_begin": "2020-04-06 21:50",
|
||||
"date_end": "2020-04-07 23:50",
|
||||
"date_result_begin": "2020-04-07 21:50",
|
||||
"date_result_end": "2020-04-07 21:50",
|
||||
"date_result_end": "2020-04-07 22:50",
|
||||
};
|
||||
|
||||
const FAKE_DATE2 = {
|
||||
|
@ -65,31 +53,18 @@ const FAKE_TEAMS2 = {
|
|||
],
|
||||
};
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
theme: Object,
|
||||
}
|
||||
type Props = {}
|
||||
|
||||
type State = {
|
||||
selectedTeam: string,
|
||||
hasVoted: boolean,
|
||||
voteDialogVisible: boolean,
|
||||
errorDialogVisible: boolean,
|
||||
currentError: number,
|
||||
}
|
||||
|
||||
class VoteScreen extends React.Component<Props, State> {
|
||||
export default class VoteScreen extends React.Component<Props, State> {
|
||||
|
||||
state = {
|
||||
selectedTeam: "none",
|
||||
voteDialogVisible: false,
|
||||
errorDialogVisible: false,
|
||||
currentError: 0,
|
||||
hasVoted: false,
|
||||
};
|
||||
|
||||
colors: Object;
|
||||
|
||||
teams: Array<Object>;
|
||||
hasVoted: boolean;
|
||||
datesString: Object;
|
||||
|
@ -98,13 +73,11 @@ class VoteScreen extends React.Component<Props, State> {
|
|||
today: Date;
|
||||
|
||||
mainFlatListData: Array<Object>;
|
||||
totalVotes: number;
|
||||
|
||||
authRef: Object;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.colors = props.theme.colors;
|
||||
constructor() {
|
||||
super();
|
||||
this.hasVoted = false;
|
||||
this.today = new Date();
|
||||
this.authRef = React.createRef();
|
||||
|
@ -125,10 +98,11 @@ class VoteScreen extends React.Component<Props, State> {
|
|||
};
|
||||
}
|
||||
|
||||
getDateString(date: Date, dateString: string) {
|
||||
if (this.today.getDate() === date.getDate())
|
||||
return getTimeOnlyString(dateString);
|
||||
else
|
||||
getDateString(date: Date, dateString: string): string {
|
||||
if (this.today.getDate() === date.getDate()) {
|
||||
const str = getTimeOnlyString(dateString);
|
||||
return str !== null ? str : "";
|
||||
} else
|
||||
return dateString;
|
||||
}
|
||||
|
||||
|
@ -154,7 +128,7 @@ class VoteScreen extends React.Component<Props, State> {
|
|||
|
||||
mainRenderItem = ({item}: Object) => {
|
||||
if (item.key === 'info')
|
||||
return this.getTitleCard();
|
||||
return <VoteTitle/>;
|
||||
else if (item.key === 'main' && this.isVoteAvailable())
|
||||
return this.getContent();
|
||||
else
|
||||
|
@ -176,64 +150,13 @@ class VoteScreen extends React.Component<Props, State> {
|
|||
{/*$FlowFixMe*/}
|
||||
<FlatList
|
||||
data={this.mainFlatListData}
|
||||
extraData={this.state.selectedTeam + this.state.hasVoted.toString()}
|
||||
extraData={this.state.hasVoted.toString()}
|
||||
renderItem={this.mainRenderItem}
|
||||
/>
|
||||
<LoadingConfirmDialog
|
||||
visible={this.state.voteDialogVisible}
|
||||
onDismiss={this.onVoteDialogDismiss}
|
||||
onAccept={this.onVoteDialogAccept}
|
||||
title={"VOTE?"}
|
||||
titleLoading={"SENDING VOTE..."}
|
||||
message={"SURE?"}
|
||||
/>
|
||||
<ErrorDialog
|
||||
visible={this.state.errorDialogVisible}
|
||||
onDismiss={this.onErrorDialogDismiss}
|
||||
errorCode={this.state.currentError}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
showVoteDialog = () => this.setState({voteDialogVisible: true});
|
||||
|
||||
onVoteDialogDismiss = (voteStatus: boolean) => {
|
||||
voteStatus = voteStatus === undefined ? false : voteStatus;
|
||||
this.setState({
|
||||
voteDialogVisible: false,
|
||||
hasVoted: voteStatus,
|
||||
})
|
||||
};
|
||||
|
||||
onVoteDialogAccept = async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
ConnectionManager.getInstance().authenticatedRequest(
|
||||
"elections/vote",
|
||||
["vote"],
|
||||
[parseInt(this.state.selectedTeam)])
|
||||
.then(() => {
|
||||
this.onVoteDialogDismiss(true);
|
||||
resolve();
|
||||
})
|
||||
.catch((error: number) => {
|
||||
this.onVoteDialogDismiss(false);
|
||||
this.showErrorDialog(error);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
showErrorDialog = (error: number) => this.setState({
|
||||
errorDialogVisible: true,
|
||||
currentError: error,
|
||||
});
|
||||
|
||||
onErrorDialogDismiss = () => {
|
||||
this.setState({errorDialogVisible: false});
|
||||
this.reloadData();
|
||||
};
|
||||
|
||||
getContent() {
|
||||
if (!this.isVoteStarted())
|
||||
return this.getTeaseVoteCard();
|
||||
|
@ -247,218 +170,39 @@ class VoteScreen extends React.Component<Props, State> {
|
|||
return null;
|
||||
}
|
||||
|
||||
getTitleCard() {
|
||||
return (
|
||||
<Card style={styles.card}>
|
||||
<Card.Title
|
||||
title={"VOTE"}
|
||||
subtitle={"WHY"}
|
||||
left={(props) => <Avatar.Image
|
||||
{...props}
|
||||
source={ICON_AMICALE}
|
||||
style={styles.icon}
|
||||
/>}
|
||||
/>
|
||||
<Card.Content>
|
||||
<Paragraph>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus rhoncus porttitor
|
||||
suscipit. Quisque hendrerit, quam id vestibulum vestibulum, lorem nisi hendrerit nisi, a
|
||||
eleifend sapien diam ut elit. Curabitur sit amet vulputate lectus. Donec semper cursus sapien
|
||||
vel finibus.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
Sed et venenatis turpis. Fusce malesuada magna urna, sed vehicula sem luctus in. Vivamus
|
||||
faucibus vel eros a ultricies. In sed laoreet ante, luctus mattis tellus. Etiam vitae ipsum
|
||||
sagittis, consequat purus sed, blandit risus.
|
||||
</Paragraph>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
onVoteSelectionChange = (team: string) => {
|
||||
this.setState({selectedTeam: team})
|
||||
};
|
||||
|
||||
onVotePress = () => {
|
||||
this.showVoteDialog();
|
||||
};
|
||||
|
||||
voteKeyExtractor = (item: Object) => item.id.toString();
|
||||
|
||||
voteRenderItem = ({item}: Object) => <RadioButton.Item label={item.name} value={item.id.toString()}/>;
|
||||
onVoteSuccess = () => this.setState({hasVoted: true});
|
||||
|
||||
/**
|
||||
* The user has not voted yet, and the votes are open
|
||||
*/
|
||||
getVoteCard() {
|
||||
return (
|
||||
<Card style={styles.card}>
|
||||
<Card.Title
|
||||
title={"VOTE OPEN"}
|
||||
subtitle={"VOTE NOW"}
|
||||
left={(props) => <Avatar.Icon
|
||||
{...props}
|
||||
icon={"alert-decagram"}
|
||||
/>}
|
||||
/>
|
||||
<Card.Content>
|
||||
<RadioButton.Group
|
||||
onValueChange={this.onVoteSelectionChange}
|
||||
value={this.state.selectedTeam}
|
||||
>
|
||||
{/*$FlowFixMe*/}
|
||||
<FlatList
|
||||
data={this.teams}
|
||||
keyExtractor={this.voteKeyExtractor}
|
||||
extraData={this.state.selectedTeam}
|
||||
renderItem={this.voteRenderItem}
|
||||
/>
|
||||
</RadioButton.Group>
|
||||
</Card.Content>
|
||||
<Card.Actions>
|
||||
<Button
|
||||
icon="send"
|
||||
mode="contained"
|
||||
onPress={this.onVotePress}
|
||||
style={{marginLeft: 'auto'}}
|
||||
disabled={this.state.selectedTeam === "none"}
|
||||
>
|
||||
SEND VOTE
|
||||
</Button>
|
||||
</Card.Actions>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
sortByVotes = (a: Object, b: Object) => b.votes - a.votes;
|
||||
|
||||
getTotalVotes() {
|
||||
let count = 0;
|
||||
for (let i = 0; i < this.teams.length; i++) {
|
||||
count += this.teams[i].votes;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
getWinnerId() {
|
||||
return this.teams[0].id;
|
||||
return <VoteSelect teams={this.teams} onVoteSuccess={this.onVoteSuccess} onVoteError={this.reloadData}/>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Votes have ended, results can be displayed
|
||||
*/
|
||||
getVoteResultCard() {
|
||||
this.totalVotes = this.getTotalVotes();
|
||||
this.teams.sort(this.sortByVotes);
|
||||
return (
|
||||
<Card style={styles.card}>
|
||||
<Card.Title
|
||||
title={"RESULTS"}
|
||||
subtitle={"AVAILABLE UNTIL " + this.getDateString(this.dates.date_result_end, this.datesString.date_result_end)}
|
||||
left={(props) => <Avatar.Icon
|
||||
{...props}
|
||||
icon={"podium-gold"}
|
||||
/>}
|
||||
/>
|
||||
<Card.Content>
|
||||
<Subheading>TOTAL VOTES : {this.totalVotes}</Subheading>
|
||||
{/*$FlowFixMe*/}
|
||||
<FlatList
|
||||
data={this.teams}
|
||||
keyExtractor={this.voteKeyExtractor}
|
||||
renderItem={this.resultRenderItem}
|
||||
/>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
return <VoteResults teams={this.teams}
|
||||
dateEnd={this.getDateString(this.dates.date_result_end, this.datesString.date_result_end)}/>;
|
||||
}
|
||||
|
||||
resultRenderItem = ({item}: Object) => {
|
||||
const isWinner = this.getWinnerId() === item.id;
|
||||
return (
|
||||
<Card style={{
|
||||
marginTop: 10,
|
||||
elevation: isWinner ? 5 : 3,
|
||||
}}>
|
||||
<List.Item
|
||||
title={item.name}
|
||||
description={item.votes + " VOTES"}
|
||||
left={props => isWinner
|
||||
? <List.Icon {...props} icon="trophy" color={this.colors.primary}/>
|
||||
: null}
|
||||
titleStyle={{
|
||||
color: isWinner
|
||||
? this.colors.primary
|
||||
: this.colors.text
|
||||
}}
|
||||
style={{padding: 0}}
|
||||
/>
|
||||
<ProgressBar progress={item.votes / this.totalVotes} color={this.colors.primary}/>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Vote will open shortly
|
||||
*/
|
||||
getTeaseVoteCard() {
|
||||
return (
|
||||
<Card style={styles.card}>
|
||||
<Card.Title
|
||||
title={"VOTE INCOMING"}
|
||||
subtitle={"GET READY"}
|
||||
left={props => <Avatar.Icon
|
||||
{...props}
|
||||
icon="vote"/>}
|
||||
/>
|
||||
<Card.Content>
|
||||
<Paragraph>
|
||||
VOTE STARTS
|
||||
AT {this.getDateString(this.dates.date_begin, this.datesString.date_begin)}
|
||||
</Paragraph>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
return <VoteTease startDate={this.getDateString(this.dates.date_begin, this.datesString.date_begin)}/>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Votes have ended waiting for results
|
||||
* Votes have ended, or user has voted waiting for results
|
||||
*/
|
||||
getWaitVoteCard() {
|
||||
return (
|
||||
<Card style={styles.card}>
|
||||
<Card.Title
|
||||
title={this.isVoteRunning() ? "VOTE SUBMITTED" : "VOTES HAVE ENDED"}
|
||||
subtitle={"WAITING FOR RESULTS"}
|
||||
left={(props) => <ActivityIndicator {...props}/>}
|
||||
/>
|
||||
<Card.Content>
|
||||
{
|
||||
this.state.hasVoted
|
||||
? <Paragraph style={{color: this.colors.success}}>
|
||||
VOTE SUBMITTED. THX FOR YOUR PARTICIPATION
|
||||
</Paragraph>
|
||||
: null
|
||||
}
|
||||
{
|
||||
this.hasVoted
|
||||
? <Paragraph style={{color: this.colors.success}}>
|
||||
THX FOR THE VOTE
|
||||
</Paragraph>
|
||||
: null
|
||||
}
|
||||
{
|
||||
this.dates.date_result_begin !== null
|
||||
? <Paragraph>
|
||||
RESULTS AVAILABLE
|
||||
AT {this.getDateString(this.dates.date_result_begin, this.datesString.date_result_begin)}
|
||||
</Paragraph>
|
||||
: <Paragraph>RESULTS AVAILABLE SHORTLY</Paragraph>
|
||||
}
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
let startDate = null;
|
||||
if (this.dates.date_result_begin !== null)
|
||||
startDate = this.getDateString(this.dates.date_result_begin, this.datesString.date_result_begin);
|
||||
return <VoteWait startDate={startDate} hasVoted={this.hasVoted} justVoted={this.state.hasVoted}
|
||||
isVoteRunning={this.isVoteRunning()}/>;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -481,14 +225,3 @@ class VoteScreen extends React.Component<Props, State> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
card: {
|
||||
margin: 10,
|
||||
},
|
||||
icon: {
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
});
|
||||
|
||||
export default withTheme(VoteScreen);
|
||||
|
|
Loading…
Reference in a new issue