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.

PollResults.tsx 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import React, { useCallback } from 'react';
  2. import { FlatList, Text, TextStyle, View, ViewStyle } from 'react-native';
  3. import { useSelector } from 'react-redux';
  4. import { getLocalParticipant } from '../../../base/participants/functions';
  5. import Button from '../../../base/ui/components/native/Button';
  6. import { BUTTON_TYPES } from '../../../base/ui/constants.native';
  7. import AbstractPollResults from '../AbstractPollResults';
  8. import type { AbstractProps, AnswerInfo } from '../AbstractPollResults';
  9. import { chatStyles, dialogStyles, resultsStyles } from './styles';
  10. /**
  11. * Component that renders the poll results.
  12. *
  13. * @param {Props} props - The passed props.
  14. * @returns {React.Node}
  15. */
  16. const PollResults = (props: AbstractProps) => {
  17. const {
  18. answers,
  19. changeVote,
  20. haveVoted,
  21. question,
  22. showDetails,
  23. t,
  24. toggleIsDetailed
  25. } = props;
  26. /**
  27. * Render a header summing up answer information.
  28. *
  29. * @param {string} answer - The name of the answer.
  30. * @param {number} percentage - The percentage of voters.
  31. * @param {number} nbVotes - The number of collected votes.
  32. * @returns {React.Node}
  33. */
  34. const renderHeader = (answer: string, percentage: number, nbVotes: number) => (
  35. <View style = { resultsStyles.answerHeader as ViewStyle }>
  36. <Text style = { resultsStyles.answer as TextStyle }>{ answer }</Text>
  37. <View>
  38. <Text style = { resultsStyles.answer as TextStyle }>({nbVotes}) {percentage}%</Text>
  39. </View>
  40. </View>
  41. );
  42. /**
  43. * Render voters of and answer.
  44. *
  45. * @param {AnswerInfo} answer - The answer info.
  46. * @returns {React.Node}
  47. */
  48. const renderRow = useCallback((answer: AnswerInfo) => {
  49. const { name, percentage, voters, voterCount } = answer;
  50. if (showDetails) {
  51. return (
  52. <View style = { resultsStyles.answerContainer as ViewStyle }>
  53. { renderHeader(name, percentage, voterCount) }
  54. <View style = { resultsStyles.barContainer as ViewStyle }>
  55. <View style = { [ resultsStyles.bar, { width: `${percentage}%` } ] as ViewStyle[] } />
  56. </View>
  57. { voters && voterCount > 0
  58. && <View style = { resultsStyles.voters as ViewStyle }>
  59. {/* @ts-ignore */}
  60. {voters.map(({ id, name: voterName }) =>
  61. (<Text
  62. key = { id }
  63. style = { resultsStyles.voter as TextStyle }>
  64. { voterName }
  65. </Text>)
  66. )}
  67. </View>}
  68. </View>
  69. );
  70. }
  71. // else, we display a simple list
  72. // We add a progress bar by creating an empty view of width equal to percentage.
  73. return (
  74. <View style = { resultsStyles.answerContainer as ViewStyle }>
  75. { renderHeader(answer.name, percentage, voterCount) }
  76. <View style = { resultsStyles.barContainer as ViewStyle }>
  77. <View style = { [ resultsStyles.bar, { width: `${percentage}%` } ] as ViewStyle[] } />
  78. </View>
  79. </View>
  80. );
  81. }, [ showDetails ]);
  82. const localParticipant = useSelector(getLocalParticipant);
  83. /* eslint-disable react/jsx-no-bind */
  84. return (
  85. <View>
  86. <Text style = { dialogStyles.questionText as TextStyle } >{ question }</Text>
  87. <Text style = { dialogStyles.questionOwnerText as TextStyle } >
  88. { t('polls.by', { name: localParticipant?.name }) }
  89. </Text>
  90. <FlatList
  91. data = { answers }
  92. keyExtractor = { (item, index) => index.toString() }
  93. renderItem = { answer => renderRow(answer.item) } />
  94. <View style = { chatStyles.bottomLinks as ViewStyle }>
  95. <Button
  96. labelKey = {
  97. showDetails
  98. ? 'polls.results.hideDetailedResults'
  99. : 'polls.results.showDetailedResults'
  100. }
  101. labelStyle = { chatStyles.toggleText }
  102. onClick = { toggleIsDetailed }
  103. type = { BUTTON_TYPES.TERTIARY } />
  104. <Button
  105. labelKey = {
  106. haveVoted
  107. ? 'polls.results.changeVote'
  108. : 'polls.results.vote'
  109. }
  110. labelStyle = { chatStyles.toggleText }
  111. onClick = { changeVote }
  112. type = { BUTTON_TYPES.TERTIARY } />
  113. </View>
  114. </View>
  115. );
  116. };
  117. /*
  118. * We apply AbstractPollResults to fill in the AbstractProps common
  119. * to both the web and native implementations.
  120. */
  121. // eslint-disable-next-line new-cap
  122. export default AbstractPollResults(PollResults);