Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 1979 | Rev 2970 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
813 stevensc 1
import React, { useEffect, useRef, useState } from 'react'
2
import { useForm } from 'react-hook-form'
5 stevensc 3
 
813 stevensc 4
import styles from './survey.module.scss'
2969 stevensc 5
import { axios } from '@utils'
6
import { addNotification } from '@store/notification/notification.actions'
7
import { Public, LockClock } from '@mui/icons-material'
8
import { styled } from '@mui/material'
9
import { css } from '@emotion/react'
10
import { updateFeed } from '@store/feed/feed.actions'
5 stevensc 11
 
2969 stevensc 12
const RadioButton = styled('div')`
5 stevensc 13
  display: flex;
14
  align-items: center;
15
  gap: 0.5rem;
16
  padding: 0.5rem 1rem;
17
  border: 2px solid var(--border-primary);
18
  border-radius: 50px;
19
  cursor: pointer;
20
  transition: all 200ms ease;
21
  position: relative;
22
  overflow: hidden;
23
  margin-bottom: 0.5rem;
24
  input {
25
    margin: 0 !important;
26
  }
27
  label {
28
    color: var(--font-color);
29
    font-weight: 500;
30
  }
31
  &::before {
813 stevensc 32
    content: '';
5 stevensc 33
    position: absolute;
34
    left: 0;
35
    top: 0;
36
    height: 100%;
813 stevensc 37
    width: ${(props) => (props.porcentage ? `${props.porcentage}%` : '0%')};
5 stevensc 38
    background-color: #0002;
39
    z-index: 4;
40
  }
41
  &:hover {
42
    border-color: var(--font-color);
43
    text-shadow: 0 0 1px var(--font-color);
44
  }
45
  ${(props) =>
46
    props.disabled &&
47
    css`
48
      background-color: #9992;
49
      cursor: auto;
50
 
51
      label {
52
        color: gray;
53
      }
54
 
55
      &:hover {
56
        border-color: var(--border-primary);
57
        text-shadow: none;
58
      }
59
    `}
813 stevensc 60
`
5 stevensc 61
 
2969 stevensc 62
const VoteTag = styled('span')`
5 stevensc 63
  position: absolute;
64
  bottom: 1rem;
65
  right: 1rem;
66
  color: var(--font-color) !important;
67
  font-weight: 600;
813 stevensc 68
`
5 stevensc 69
 
2969 stevensc 70
const SurveyForm = (props) => {
71
  const {
72
    active = false,
73
    question,
74
    answers = [],
75
    votes,
76
    time,
77
    resultType,
78
    voteUrl
79
  } = props
80
 
81
  console.log(props)
82
 
813 stevensc 83
  const [remainingTime, setRemainingTime] = useState('00:00:00')
84
  const [isActive, setIsActive] = useState(true)
85
  const [totalVotes, setTotalVotes] = useState(0)
86
  const timeRef = useRef(time)
87
  const { register, handleSubmit } = useForm()
5 stevensc 88
 
89
  const sendVote = handleSubmit(({ vote }) => {
813 stevensc 90
    setIsActive(false)
5 stevensc 91
 
1979 stevensc 92
    const formData = new FormData()
93
    formData.append('vote', vote)
94
 
5 stevensc 95
    axios
1979 stevensc 96
      .post(voteUrl, formData)
5 stevensc 97
      .then(({ data: response }) => {
813 stevensc 98
        const { success, data } = response
99
 
5 stevensc 100
        if (!success) {
814 stevensc 101
          const errorMessage =
102
            typeof data === 'string'
103
              ? data
104
              : 'Error interno, por favor intente mas tarde.'
105
          throw new Error(errorMessage)
5 stevensc 106
        }
107
 
813 stevensc 108
        updateFeed({ feed: data, uuid: data.feed_uuid })
109
        addNotification({ style: 'success', msg: 'Voto emitido con exito' })
5 stevensc 110
      })
111
      .catch((err) => {
813 stevensc 112
        setIsActive(true)
814 stevensc 113
        addNotification({ style: 'danger', msg: err.message })
813 stevensc 114
      })
115
  })
5 stevensc 116
 
117
  function getTimeDiff(segundos) {
813 stevensc 118
    const currentDate = new Date()
119
    const futureDate = new Date(currentDate.getTime() + segundos * 1000)
120
    const diff = futureDate - currentDate
5 stevensc 121
 
813 stevensc 122
    const days = Math.floor(diff / (1000 * 60 * 60 * 24))
123
    const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
124
    const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
5 stevensc 125
 
813 stevensc 126
    return `${addZero(days)}d ${addZero(hours)}h ${addZero(minutes)}m`
5 stevensc 127
  }
128
 
129
  function addZero(unit) {
813 stevensc 130
    return String(unit).padStart(2, '0')
5 stevensc 131
  }
132
 
133
  function getPorcentage(n, total) {
813 stevensc 134
    return (n / total) * 100
5 stevensc 135
  }
136
 
137
  useEffect(() => {
813 stevensc 138
    setRemainingTime(getTimeDiff(time))
5 stevensc 139
 
813 stevensc 140
    if (!time) return
5 stevensc 141
 
142
    const interval = setInterval(() => {
143
      if (!timeRef.current) {
813 stevensc 144
        setRemainingTime(() => getTimeDiff(0))
145
        setIsActive(false)
146
        return
5 stevensc 147
      }
148
 
149
      if (!timeRef.current <= 60) {
813 stevensc 150
        timeRef.current -= 1
151
        setRemainingTime(() => getTimeDiff(timeRef.current))
152
        return
5 stevensc 153
      }
154
 
813 stevensc 155
      timeRef.current -= 60
156
      setRemainingTime(() => getTimeDiff(timeRef.current))
157
    }, 60000)
5 stevensc 158
 
159
    return () => {
813 stevensc 160
      clearInterval(interval)
161
    }
162
  }, [])
5 stevensc 163
 
164
  useEffect(() => {
814 stevensc 165
    const total = votes.reduce((acum, current) => {
166
      if (!current) {
167
        return acum
168
      }
169
 
170
      return acum + Number(current)
171
    }, 0)
172
 
813 stevensc 173
    setTotalVotes(total)
174
  }, [votes])
5 stevensc 175
 
176
  useEffect(() => {
814 stevensc 177
    setIsActive(!!active)
813 stevensc 178
  }, [active])
5 stevensc 179
 
180
  return (
181
    <form onChange={sendVote} className={styles.survey_form}>
182
      <h3>{question}</h3>
813 stevensc 183
      {resultType === 'pu' && (
5 stevensc 184
        <span
813 stevensc 185
          className='mb-2'
186
          title='El número de votos es visible para todos los usuarios'
5 stevensc 187
        >
2969 stevensc 188
          <Public /> Público
5 stevensc 189
        </span>
190
      )}
813 stevensc 191
      {resultType === 'pr' && (
5 stevensc 192
        <span
813 stevensc 193
          className='mb-2'
194
          title='Los resultados de la votación son privados'
5 stevensc 195
        >
2969 stevensc 196
          <LockClock /> Privado
5 stevensc 197
        </span>
198
      )}
199
      {answers.map(
200
        (option, index) =>
201
          option && (
202
            <RadioButton
203
              disabled={!isActive}
204
              porcentage={
205
                !!totalVotes && getPorcentage(votes[index], totalVotes)
206
              }
207
              key={index}
208
            >
209
              <input
813 stevensc 210
                type='radio'
211
                name='vote'
5 stevensc 212
                id={`vote-${index + 1}`}
213
                disabled={!isActive}
214
                ref={register({ required: true })}
215
                value={index + 1}
216
              />
217
              <label htmlFor={`vote-${index + 1}`}>{option}</label>
218
              {!!totalVotes && (
813 stevensc 219
                <span className='mb-0'>
5 stevensc 220
                  {getPorcentage(votes[index], totalVotes)}%
221
                </span>
222
              )}
223
            </RadioButton>
224
          )
225
      )}
226
      <span>Tiempo restante: {remainingTime}</span>
227
      {!isActive && <VoteTag>Tu voto ya fue emitido</VoteTag>}
228
    </form>
813 stevensc 229
  )
230
}
5 stevensc 231
 
2969 stevensc 232
export default SurveyForm