Application Android et IOS pour l'amicale des élèves
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.

VoteSelect.tsx 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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. import * as React from 'react';
  20. import {Avatar, Button, Card, RadioButton} from 'react-native-paper';
  21. import {FlatList, StyleSheet, View} from 'react-native';
  22. import i18n from 'i18n-js';
  23. import ConnectionManager from '../../../managers/ConnectionManager';
  24. import LoadingConfirmDialog from '../../Dialogs/LoadingConfirmDialog';
  25. import ErrorDialog from '../../Dialogs/ErrorDialog';
  26. import type {VoteTeamType} from '../../../screens/Amicale/VoteScreen';
  27. type PropsType = {
  28. teams: Array<VoteTeamType>;
  29. onVoteSuccess: () => void;
  30. onVoteError: () => void;
  31. };
  32. type StateType = {
  33. selectedTeam: string;
  34. voteDialogVisible: boolean;
  35. errorDialogVisible: boolean;
  36. currentError: number;
  37. };
  38. const styles = StyleSheet.create({
  39. card: {
  40. margin: 10,
  41. },
  42. icon: {
  43. backgroundColor: 'transparent',
  44. },
  45. });
  46. export default class VoteSelect extends React.PureComponent<
  47. PropsType,
  48. StateType
  49. > {
  50. constructor(props: PropsType) {
  51. super(props);
  52. this.state = {
  53. selectedTeam: 'none',
  54. voteDialogVisible: false,
  55. errorDialogVisible: false,
  56. currentError: 0,
  57. };
  58. }
  59. onVoteSelectionChange = (teamName: string): void =>
  60. this.setState({selectedTeam: teamName});
  61. voteKeyExtractor = (item: VoteTeamType): string => item.id.toString();
  62. voteRenderItem = ({item}: {item: VoteTeamType}) => (
  63. <RadioButton.Item label={item.name} value={item.id.toString()} />
  64. );
  65. showVoteDialog = (): void => this.setState({voteDialogVisible: true});
  66. onVoteDialogDismiss = (): void => this.setState({voteDialogVisible: false});
  67. onVoteDialogAccept = async (): Promise<void> => {
  68. return new Promise((resolve: () => void) => {
  69. const {state} = this;
  70. ConnectionManager.getInstance()
  71. .authenticatedRequest('elections/vote', {
  72. team: parseInt(state.selectedTeam, 10),
  73. })
  74. .then(() => {
  75. this.onVoteDialogDismiss();
  76. const {props} = this;
  77. props.onVoteSuccess();
  78. resolve();
  79. })
  80. .catch((error: number) => {
  81. this.onVoteDialogDismiss();
  82. this.showErrorDialog(error);
  83. resolve();
  84. });
  85. });
  86. };
  87. showErrorDialog = (error: number): void =>
  88. this.setState({
  89. errorDialogVisible: true,
  90. currentError: error,
  91. });
  92. onErrorDialogDismiss = () => {
  93. this.setState({errorDialogVisible: false});
  94. const {props} = this;
  95. props.onVoteError();
  96. };
  97. render() {
  98. const {state, props} = this;
  99. return (
  100. <View>
  101. <Card style={styles.card}>
  102. <Card.Title
  103. title={i18n.t('screens.vote.select.title')}
  104. subtitle={i18n.t('screens.vote.select.subtitle')}
  105. left={(iconProps) => (
  106. <Avatar.Icon size={iconProps.size} icon="alert-decagram" />
  107. )}
  108. />
  109. <Card.Content>
  110. <RadioButton.Group
  111. onValueChange={this.onVoteSelectionChange}
  112. value={state.selectedTeam}>
  113. <FlatList
  114. data={props.teams}
  115. keyExtractor={this.voteKeyExtractor}
  116. extraData={state.selectedTeam}
  117. renderItem={this.voteRenderItem}
  118. />
  119. </RadioButton.Group>
  120. </Card.Content>
  121. <Card.Actions>
  122. <Button
  123. icon="send"
  124. mode="contained"
  125. onPress={this.showVoteDialog}
  126. style={{marginLeft: 'auto'}}
  127. disabled={state.selectedTeam === 'none'}>
  128. {i18n.t('screens.vote.select.sendButton')}
  129. </Button>
  130. </Card.Actions>
  131. </Card>
  132. <LoadingConfirmDialog
  133. visible={state.voteDialogVisible}
  134. onDismiss={this.onVoteDialogDismiss}
  135. onAccept={this.onVoteDialogAccept}
  136. title={i18n.t('screens.vote.select.dialogTitle')}
  137. titleLoading={i18n.t('screens.vote.select.dialogTitleLoading')}
  138. message={i18n.t('screens.vote.select.dialogMessage')}
  139. />
  140. <ErrorDialog
  141. visible={state.errorDialogVisible}
  142. onDismiss={this.onErrorDialogDismiss}
  143. errorCode={state.currentError}
  144. />
  145. </View>
  146. );
  147. }
  148. }