Rev 7147 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
import React, { useEffect, useRef, useState } from 'react'import { axios } from '../../utils'import { useForm } from 'react-hook-form'import { connect } from 'react-redux'import { updateFeed } from '../../redux/feed/feed.actions'import { addNotification } from '../../redux/notification/notification.actions'import LockClockIcon from '@mui/icons-material/LockClock'import PublicIcon from '@mui/icons-material/Public'import styles from './survey.module.scss'import styled, { css } from 'styled-components'const RadioButton = styled.div`display: flex;align-items: center;gap: 0.5rem;padding: 0.5rem 1rem;border: 2px solid var(--border-primary);border-radius: 50px;cursor: pointer;transition: all 200ms ease;position: relative;overflow: hidden;margin-bottom: 0.5rem;input {margin: 0 !important;}label {color: var(--font-color);font-weight: 500;}&::before {content: '';position: absolute;left: 0;top: 0;height: 100%;width: ${(props) => (props.porcentage ? `${props.porcentage}%` : '0%')};background-color: #0002;z-index: 4;}&:hover {border-color: var(--font-color);text-shadow: 0 0 1px var(--font-color);}${(props) =>props.disabled &&css`background-color: #9992;cursor: auto;label {color: gray;}&:hover {border-color: var(--border-primary);text-shadow: none;}`}`const VoteTag = styled.span`position: absolute;bottom: 1rem;right: 1rem;color: var(--font-color) !important;font-weight: 600;`const SurveyForm = ({question,answers = [],votes,active,time,resultType,voteUrl,addNotification, // Redux actionupdateFeed, // Redux action}) => {const [remainingTime, setRemainingTime] = useState('00:00:00')const [isActive, setIsActive] = useState(Boolean(active))const [totalVotes, setTotalVotes] = useState(0)const timeRef = useRef(time)const { register, handleSubmit } = useForm()const sendVote = handleSubmit(({ vote }) => {setIsActive(false)const formData = new FormData()formData.append('vote', vote)axios.post(voteUrl, formData).then(({ data: response }) => {const { success, data } = responseif (!success) {addNotification({ style: 'danger', msg: `Error: ${data}` })setIsActive(true)}updateFeed({ feed: data, uuid: data.feed_uuid })addNotification({ style: 'success', msg: 'Voto emitido con exito' })}).catch((err) => {addNotification({ style: 'danger', msg: `Error: ${err}` })setIsActive(true)throw new Error(err)})})function getTimeDiff(segundos) {// Obtener la fecha y hora actualconst currentDate = new Date()// Calcular la fecha y hora futura sumando los segundos proporcionadosconst futureDate = new Date(currentDate.getTime() + segundos * 1000)// Calcular la diferencia entre la fecha futura y la fecha actualconst diff = futureDate - currentDate// Calcular los componentes de la diferencia de tiempoconst days = Math.floor(diff / (1000 * 60 * 60 * 24))const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))// Devolver el resultadoreturn `${addZero(days)}d ${addZero(hours)}h ${addZero(minutes)}m`}function addZero(unit) {return String(unit).padStart(2, '0')}function getPorcentage(n, total) {return (n / total) * 100}useEffect(() => {setRemainingTime(getTimeDiff(time))if (!time) returnconst interval = setInterval(() => {if (!timeRef.current) {setRemainingTime(() => getTimeDiff(0))setIsActive(false)return}if (!timeRef.current <= 60) {timeRef.current -= 1setRemainingTime(() => getTimeDiff(timeRef.current))return}timeRef.current -= 60setRemainingTime(() => getTimeDiff(timeRef.current))}, 60000)return () => {clearInterval(interval)}}, [])useEffect(() => {if (!votes) returnconst total = votes.reduce((acum, current) => acum + Number(current), 0)setTotalVotes(total)}, [votes])return (<form onChange={sendVote} className={styles.survey_form}><h3>{question}</h3>{resultType === 'pu' && (<spanclassName="mb-2"title="El número de votos es visible para todos los usuarios"><PublicIcon /> Público</span>)}{resultType === 'pr' && (<spanclassName="mb-2"title="Los resultados de la votación son privados"><LockClockIcon /> Privado</span>)}{answers.map((option, index) =>option && (<RadioButtondisabled={!isActive}porcentage={totalVotes && getPorcentage(votes[index], totalVotes)}key={index}><inputtype="radio"name="vote"id={`vote-${index + 1}`}disabled={!isActive}ref={register({ required: true })}value={index + 1}/><label htmlFor={`vote-${index + 1}`}>{option}</label>{totalVotes && (<span className="mb-0">{getPorcentage(votes[index], totalVotes)}%</span>)}</RadioButton>))}<span>Tiempo restante: {remainingTime}</span>{!isActive && <VoteTag>Tu voto ya fue emitido</VoteTag>}</form>)}const mapDispatchToProps = {addNotification: (notification) => addNotification(notification),updateFeed: (payload) => updateFeed(payload),}export default connect(null, mapDispatchToProps)(SurveyForm)