Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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

Rev Autor Línea Nro. Línea
6436 stevensc 1
import React, { useEffect, useRef, useState } from 'react'
6393 stevensc 2
import { axios } from '../../../utils'
6392 stevensc 3
import { useForm } from 'react-hook-form'
6393 stevensc 4
import { connect } from 'react-redux'
5
 
6410 stevensc 6
import { updateFeed } from '../../../redux/feed/feed.actions'
6392 stevensc 7
import { addNotification } from '../../../redux/notification/notification.actions'
6390 stevensc 8
 
6410 stevensc 9
import LockClockIcon from '@mui/icons-material/LockClock'
10
import PublicIcon from '@mui/icons-material/Public'
11
 
6393 stevensc 12
import styles from './survey.module.scss'
6440 stevensc 13
import styled, { css } from 'styled-components'
6393 stevensc 14
 
6440 stevensc 15
const RadioButton = styled.div`
16
  display: flex;
17
  align-items: center;
18
  gap: 0.5rem;
19
  padding: 0.5rem 1rem;
20
  margin-bottom: 0.5rem;
6441 stevensc 21
  border: 2px solid var(--border-primary);
6440 stevensc 22
  border-radius: 50px;
23
  cursor: pointer;
24
  transition: all 200ms ease;
25
  position: relative;
6442 stevensc 26
  overflow: hidden;
6440 stevensc 27
 
28
  input {
29
    margin: 0 !important;
30
  }
31
 
32
  label {
6441 stevensc 33
    color: var(--font-color);
6440 stevensc 34
    font-weight: 500;
35
  }
36
 
37
  &::before {
6447 stevensc 38
    content: '';
6440 stevensc 39
    position: absolute;
40
    left: 0;
41
    top: 0;
42
    height: 100%;
6447 stevensc 43
    width: ${(props) => (props.porcentage ? `${props.porcentage}%` : '0%')};
6449 stevensc 44
    background-color: #0002;
6440 stevensc 45
    z-index: 4;
46
  }
47
 
48
  &:hover {
6441 stevensc 49
    border-color: var(--font-color);
50
    text-shadow: 0 0 1px var(--font-color);
6440 stevensc 51
  }
52
 
53
  ${(props) =>
6446 stevensc 54
    props.disabled &&
6440 stevensc 55
    css`
6446 stevensc 56
      background-color: #9992;
6440 stevensc 57
      cursor: auto;
58
 
59
      label {
60
        color: gray;
61
      }
62
 
63
      &:hover {
6441 stevensc 64
        border-color: var(--border-primary);
6440 stevensc 65
        text-shadow: none;
66
      }
67
    `}
68
`
69
 
6393 stevensc 70
const SurveyForm = ({
71
  question,
72
  answers = [],
6449 stevensc 73
  votes,
6393 stevensc 74
  active,
75
  time,
6401 stevensc 76
  resultType,
6393 stevensc 77
  voteUrl,
6401 stevensc 78
  addNotification, // Redux action
79
  updateFeed, // Redux action
6393 stevensc 80
}) => {
6438 stevensc 81
  const [remainingTime, setRemainingTime] = useState('00:00:00')
6395 stevensc 82
  const [isActive, setIsActive] = useState(Boolean(active))
6436 stevensc 83
  const timeRef = useRef(time)
6449 stevensc 84
  const voteRef = useRef(0)
6393 stevensc 85
  const { register, handleSubmit } = useForm()
6390 stevensc 86
 
6395 stevensc 87
  const sendVote = handleSubmit(({ vote }) => {
88
    setIsActive(false)
6392 stevensc 89
    const formData = new FormData()
90
 
6395 stevensc 91
    formData.append('vote', vote)
92
 
6392 stevensc 93
    axios
94
      .post(voteUrl, formData)
95
      .then(({ data: response }) => {
96
        const { success, data } = response
97
        if (!success) {
98
          addNotification({ style: 'danger', msg: `Error: ${data}` })
6395 stevensc 99
          setIsActive(true)
6392 stevensc 100
        }
101
 
6407 stevensc 102
        updateFeed({ feed: data, uuid: data.feed_uuid })
6392 stevensc 103
      })
104
      .catch((err) => {
105
        addNotification({ style: 'danger', msg: `Error: ${err}` })
6395 stevensc 106
        setIsActive(true)
6392 stevensc 107
        throw new Error(err)
108
      })
6393 stevensc 109
  })
6392 stevensc 110
 
6415 stevensc 111
  function getTimeDiff(segundos) {
112
    // Obtener la fecha y hora actual
113
    const currentDate = new Date()
114
 
115
    // Calcular la fecha y hora futura sumando los segundos proporcionados
6416 stevensc 116
    const futureDate = new Date(currentDate.getTime() + segundos * 1000)
6415 stevensc 117
 
118
    // Calcular la diferencia entre la fecha futura y la fecha actual
119
    const diff = futureDate - currentDate
120
 
121
    // Calcular los componentes de la diferencia de tiempo
6419 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))
6415 stevensc 125
 
126
    // Devolver el resultado
6449 stevensc 127
    return `${addZero(days)}días ${addZero(hours)} horas ${addZero(
128
      minutes
129
    )} minutos`
6415 stevensc 130
  }
131
 
6438 stevensc 132
  function addZero(unit) {
133
    return String(unit).padStart(2, '0')
134
  }
135
 
6439 stevensc 136
  function getPorcentage(n, total) {
6453 stevensc 137
    return (n / total) * 100
6439 stevensc 138
  }
139
 
6415 stevensc 140
  useEffect(() => {
6421 stevensc 141
    setRemainingTime(getTimeDiff(time))
142
 
6450 stevensc 143
    if (!time) return
144
 
6433 stevensc 145
    const interval = setInterval(() => {
6455 stevensc 146
      if (!timeRef.current) {
147
        setRemainingTime(() => getTimeDiff(0))
148
        return
149
      }
150
 
151
      if (!timeRef.current <= 60) {
152
        timeRef.current -= 1
153
        setRemainingTime(() => getTimeDiff(timeRef.current))
154
        return
155
      }
156
 
157
      timeRef.current -= 60
6436 stevensc 158
      setRemainingTime(() => getTimeDiff(timeRef.current))
6437 stevensc 159
    }, 60000)
6417 stevensc 160
 
6433 stevensc 161
    return () => {
162
      clearInterval(interval)
163
    }
164
  }, [])
165
 
6449 stevensc 166
  useEffect(() => {
6452 stevensc 167
    if (!votes) return
168
    votes.forEach((vote) => (voteRef.current += Number(vote)))
6449 stevensc 169
  }, [])
170
 
6390 stevensc 171
  return (
6392 stevensc 172
    <form onChange={sendVote} className={styles.survey_form}>
6390 stevensc 173
      <h3>{question}</h3>
6410 stevensc 174
      {resultType === 'pu' && (
6450 stevensc 175
        <span
176
          title="Los resultados estaran disponibles al finalizar la
177
          encuesta."
178
        >
179
          <PublicIcon /> Público
6410 stevensc 180
        </span>
181
      )}
182
      {resultType === 'pr' && (
6450 stevensc 183
        <span title="Los resultados de la votación son privados.">
6454 stevensc 184
          <LockClockIcon /> Privado
6410 stevensc 185
        </span>
186
      )}
6390 stevensc 187
      {answers.map(
188
        (option, index) =>
189
          option && (
6449 stevensc 190
            <RadioButton
191
              disabled={!isActive}
192
              porcentage={
193
                !time && votes && getPorcentage(votes[index], voteRef.current)
194
              }
195
              key={index}
196
            >
6390 stevensc 197
              <input
198
                type="radio"
6392 stevensc 199
                name="vote"
200
                id={`vote-${index + 1}`}
6390 stevensc 201
                disabled={!isActive}
6392 stevensc 202
                ref={register({ required: true })}
203
                value={index + 1}
6390 stevensc 204
              />
6392 stevensc 205
              <label htmlFor={`vote-${index + 1}`}>{option}</label>
6450 stevensc 206
              {!time && votes && (
207
                <span className="mb-0">
208
                  {getPorcentage(votes[index], voteRef.current)}%
209
                </span>
210
              )}
6440 stevensc 211
            </RadioButton>
6390 stevensc 212
          )
213
      )}
6438 stevensc 214
      <span>Tiempo restante: {remainingTime}</span>
6390 stevensc 215
    </form>
216
  )
217
}
218
 
6393 stevensc 219
const mapDispatchToProps = {
220
  addNotification: (notification) => addNotification(notification),
6401 stevensc 221
  updateFeed: (payload) => updateFeed(payload),
6393 stevensc 222
}
223
 
224
export default connect(null, mapDispatchToProps)(SurveyForm)