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.

VoteSelect.tsx 5.1KB

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