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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import ReducerRegistry from '../base/redux/ReducerRegistry';
  2. import {
  3. CHANGE_VOTE,
  4. CLEAR_POLLS,
  5. EDIT_POLL,
  6. RECEIVE_ANSWER,
  7. RECEIVE_POLL,
  8. REGISTER_VOTE,
  9. REMOVE_POLL,
  10. RESET_NB_UNREAD_POLLS,
  11. SAVE_POLL
  12. } from './actionTypes';
  13. import { IAnswer, IPoll } from './types';
  14. const INITIAL_STATE = {
  15. polls: {},
  16. // Number of not read message
  17. nbUnreadPolls: 0
  18. };
  19. export interface IPollsState {
  20. nbUnreadPolls: number;
  21. polls: {
  22. [pollId: string]: IPoll;
  23. };
  24. }
  25. const STORE_NAME = 'features/polls';
  26. ReducerRegistry.register<IPollsState>(STORE_NAME, (state = INITIAL_STATE, action): IPollsState => {
  27. switch (action.type) {
  28. case CHANGE_VOTE: {
  29. const { pollId, value } = action;
  30. return {
  31. ...state,
  32. polls: {
  33. ...state.polls,
  34. [pollId]: {
  35. ...state.polls[pollId],
  36. changingVote: value,
  37. showResults: !value
  38. }
  39. }
  40. };
  41. }
  42. case CLEAR_POLLS: {
  43. return {
  44. ...state,
  45. ...INITIAL_STATE
  46. };
  47. }
  48. // Reducer triggered when a poll is received or saved.
  49. case RECEIVE_POLL: {
  50. return {
  51. ...state,
  52. polls: {
  53. ...state.polls,
  54. [action.pollId]: action.poll
  55. },
  56. nbUnreadPolls: state.nbUnreadPolls + 1
  57. };
  58. }
  59. case SAVE_POLL: {
  60. return {
  61. ...state,
  62. polls: {
  63. ...state.polls,
  64. [action.pollId]: action.poll
  65. }
  66. };
  67. }
  68. // Reducer triggered when an answer is received
  69. // The answer is added to an existing poll
  70. case RECEIVE_ANSWER: {
  71. const { pollId, answer }: { answer: IAnswer; pollId: string; } = action;
  72. // if the poll doesn't exist
  73. if (!(pollId in state.polls)) {
  74. console.warn('requested poll does not exist: pollId ', pollId);
  75. return state;
  76. }
  77. // if the poll exists, we update it with the incoming answer
  78. const newAnswers = state.polls[pollId].answers
  79. .map(_answer => {
  80. // checking if the voters is an array for supporting old structure model
  81. const answerVoters = _answer.voters
  82. ? _answer.voters.length
  83. ? [ ..._answer.voters ] : Object.keys(_answer.voters) : [];
  84. return {
  85. name: _answer.name,
  86. voters: answerVoters
  87. };
  88. });
  89. for (let i = 0; i < newAnswers.length; i++) {
  90. // if the answer was chosen, we add the senderId to the array of voters of this answer
  91. const voters = newAnswers[i].voters as any;
  92. const index = voters.indexOf(answer.voterId);
  93. if (answer.answers[i]) {
  94. if (index === -1) {
  95. voters.push(answer.voterId);
  96. }
  97. } else if (index > -1) {
  98. voters.splice(index, 1);
  99. }
  100. }
  101. // finally we update the state by returning the updated poll
  102. return {
  103. ...state,
  104. polls: {
  105. ...state.polls,
  106. [pollId]: {
  107. ...state.polls[pollId],
  108. answers: newAnswers
  109. }
  110. }
  111. };
  112. }
  113. case REGISTER_VOTE: {
  114. const { answers, pollId }: { answers: Array<boolean> | null; pollId: string; } = action;
  115. return {
  116. ...state,
  117. polls: {
  118. ...state.polls,
  119. [pollId]: {
  120. ...state.polls[pollId],
  121. changingVote: false,
  122. lastVote: answers,
  123. showResults: true
  124. }
  125. }
  126. };
  127. }
  128. case RESET_NB_UNREAD_POLLS: {
  129. return {
  130. ...state,
  131. nbUnreadPolls: 0
  132. };
  133. }
  134. case EDIT_POLL: {
  135. return {
  136. ...state,
  137. polls: {
  138. ...state.polls,
  139. [action.pollId]: {
  140. ...state.polls[action.pollId],
  141. editing: action.editing
  142. }
  143. }
  144. };
  145. }
  146. case REMOVE_POLL: {
  147. if (Object.keys(state.polls ?? {})?.length === 1) {
  148. return {
  149. ...state,
  150. ...INITIAL_STATE
  151. };
  152. }
  153. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  154. const { [action.pollId]: _removedPoll, ...newState } = state.polls;
  155. return {
  156. ...state,
  157. polls: {
  158. ...newState
  159. }
  160. };
  161. }
  162. default:
  163. return state;
  164. }
  165. });