Application Android et IOS pour l'amicale des élèves https://play.google.com/store/apps/details?id=fr.amicaleinsat.application
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

VoteResults.js 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * Copyright (c) 2019 - 2020 Arnaud Vergnet.
  3. *
  4. * This file is part of Campus INSAT.
  5. *
  6. * Campus INSAT is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Campus INSAT is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. // @flow
  20. import * as React from 'react';
  21. import {
  22. Avatar,
  23. Card,
  24. List,
  25. ProgressBar,
  26. Subheading,
  27. withTheme,
  28. } from 'react-native-paper';
  29. import {FlatList, StyleSheet} from 'react-native';
  30. import i18n from 'i18n-js';
  31. import type {VoteTeamType} from '../../../screens/Amicale/VoteScreen';
  32. import type {CustomThemeType} from '../../../managers/ThemeManager';
  33. import type {
  34. CardTitleIconPropsType,
  35. ListIconPropsType,
  36. } from '../../../constants/PaperStyles';
  37. type PropsType = {
  38. teams: Array<VoteTeamType>,
  39. dateEnd: string,
  40. theme: CustomThemeType,
  41. };
  42. const styles = StyleSheet.create({
  43. card: {
  44. margin: 10,
  45. },
  46. icon: {
  47. backgroundColor: 'transparent',
  48. },
  49. });
  50. class VoteResults extends React.Component<PropsType> {
  51. totalVotes: number;
  52. winnerIds: Array<number>;
  53. constructor(props: PropsType) {
  54. super();
  55. props.teams.sort(this.sortByVotes);
  56. this.getTotalVotes(props.teams);
  57. this.getWinnerIds(props.teams);
  58. }
  59. shouldComponentUpdate(): boolean {
  60. return false;
  61. }
  62. getTotalVotes(teams: Array<VoteTeamType>) {
  63. this.totalVotes = 0;
  64. for (let i = 0; i < teams.length; i += 1) {
  65. this.totalVotes += teams[i].votes;
  66. }
  67. }
  68. getWinnerIds(teams: Array<VoteTeamType>) {
  69. const max = teams[0].votes;
  70. this.winnerIds = [];
  71. for (let i = 0; i < teams.length; i += 1) {
  72. if (teams[i].votes === max) this.winnerIds.push(teams[i].id);
  73. else break;
  74. }
  75. }
  76. sortByVotes = (a: VoteTeamType, b: VoteTeamType): number => b.votes - a.votes;
  77. voteKeyExtractor = (item: VoteTeamType): string => item.id.toString();
  78. resultRenderItem = ({item}: {item: VoteTeamType}): React.Node => {
  79. const isWinner = this.winnerIds.indexOf(item.id) !== -1;
  80. const isDraw = this.winnerIds.length > 1;
  81. const {props} = this;
  82. return (
  83. <Card
  84. style={{
  85. marginTop: 10,
  86. elevation: isWinner ? 5 : 3,
  87. }}>
  88. <List.Item
  89. title={item.name}
  90. description={`${item.votes} ${i18n.t('screens.vote.results.votes')}`}
  91. left={(iconProps: ListIconPropsType): React.Node =>
  92. isWinner ? (
  93. <List.Icon
  94. style={iconProps.style}
  95. icon={isDraw ? 'trophy-outline' : 'trophy'}
  96. color={props.theme.colors.primary}
  97. />
  98. ) : null
  99. }
  100. titleStyle={{
  101. color: isWinner
  102. ? props.theme.colors.primary
  103. : props.theme.colors.text,
  104. }}
  105. style={{padding: 0}}
  106. />
  107. <ProgressBar
  108. progress={item.votes / this.totalVotes}
  109. color={props.theme.colors.primary}
  110. />
  111. </Card>
  112. );
  113. };
  114. render(): React.Node {
  115. const {props} = this;
  116. return (
  117. <Card style={styles.card}>
  118. <Card.Title
  119. title={i18n.t('screens.vote.results.title')}
  120. subtitle={`${i18n.t('screens.vote.results.subtitle')} ${
  121. props.dateEnd
  122. }`}
  123. left={(iconProps: CardTitleIconPropsType): React.Node => (
  124. <Avatar.Icon size={iconProps.size} icon="podium-gold" />
  125. )}
  126. />
  127. <Card.Content>
  128. <Subheading>{`${i18n.t('screens.vote.results.totalVotes')} ${
  129. this.totalVotes
  130. }`}</Subheading>
  131. {/* $FlowFixMe */}
  132. <FlatList
  133. data={props.teams}
  134. keyExtractor={this.voteKeyExtractor}
  135. renderItem={this.resultRenderItem}
  136. />
  137. </Card.Content>
  138. </Card>
  139. );
  140. }
  141. }
  142. export default withTheme(VoteResults);