Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 3654 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |

import React, { useMemo } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { FormControlLabel, Radio, RadioGroup, styled, Typography } from '@mui/material';
import Public from '@mui/icons-material/Public';
import LockClock from '@mui/icons-material/LockClock';

import { axios } from '@utils';
import { getTimeDiff } from '@utils/dates';
import { updateFeed } from '@store/feed/feed.actions';
import { addNotification } from '@store/notification/notification.actions';

import FormErrorFeedback from '@components/UI/form/FormErrorFeedback';

const AnswerContainer = 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;
  &:hover {
    border-color: var(--font-color);
    text-shadow: 0 0 1px var(--font-color);
  }
`;

const SurveyForm = ({
  active = false,
  question = '¿Cómo consideras el ambiente laboral?',
  answers = [],
  votes = [],
  time = 0,
  voteUrl = '/feed/vote/d454717c-ba6f-485c-b94c-4fbb5f5bed94',
  resultType = 'pu'
}) => {
  const totalVotes = useMemo(
    () =>
      votes.reduce((acc, cur) => {
        if (!cur) return acc;
        return acc + cur;
      }, 0),
    [votes]
  );
  const timeRemaining = useMemo(() => getTimeDiff(time), [time]);

  const { control, handleSubmit } = useForm();

  const sendVote = handleSubmit(({ vote }) => {
    const formData = new FormData();
    formData.append('vote', vote);

    axios
      .post(voteUrl, formData)
      .then((response) => {
        const { success, data } = response.data;

        if (!success) {
          const errorMessage =
            typeof data === 'string' ? data : 'Error interno, por favor intente mas tarde.';
          throw new Error(errorMessage);
        }

        updateFeed({ feed: data, uuid: data.feed_uuid });
        addNotification({ style: 'success', msg: 'Voto emitido con exito' });
      })
      .catch((err) => {
        addNotification({ style: 'danger', msg: err.message });
      });
  });

  function getPorcentage(n, total) {
    return (n / total) * 100;
  }

  return (
    <>
      <Typography variant='h3'>{question}</Typography>

      {resultType === 'pu' ? (
        <Typography
          variant='overline'
          title='El número de votos es visible para todos los usuarios'
          sx={{ paddingBottom: (theme) => theme.spacing(0.5) }}
        >
          <Public sx={{ fontSize: '1.3rem' }} /> Público
        </Typography>
      ) : (
        <Typography
          variant='overline'
          title='Los resultados de la votación son privados'
          sx={{ paddingBottom: (theme) => theme.spacing(0.5) }}
        >
          <LockClock sx={{ fontSize: '1.3rem' }} /> Privado
        </Typography>
      )}

      <form onChange={sendVote}>
        <Controller
          name='vote'
          control={control}
          rules={{ required: 'Por favor seleccione una opción' }}
          defaultValue=''
          disabled={!active}
          render={({ field, fieldState: { error } }) => (
            <>
              <RadioGroup {...field}>
                {answers.map((answer, index) => {
                  if (answer === null) return null;

                  return (
                    <AnswerContainer
                      key={answer}
                      sx={{
                        '::before': {
                          content: '',
                          position: 'absolute',
                          left: 0,
                          top: 0,
                          height: '100%',
                          backgroundColor: '#0002',
                          zIndex: 4,
                          width: totalVotes ? `${getPorcentage(votes[index], totalVotes)}%` : 0
                        }
                      }}
                    >
                      <FormControlLabel
                        value={index + 1}
                        control={<Radio sx={{ padding: 0 }} />}
                        label={answer}
                        sx={{ margin: 0, gap: 1 }}
                        disabled={field.disabled}
                      />

                      {totalVotes ? (
                        <Typography variant='overline'>
                          {getPorcentage(votes[index], totalVotes)}%
                        </Typography>
                      ) : null}
                    </AnswerContainer>
                  );
                })}
              </RadioGroup>
              {error && <FormErrorFeedback>{error.message}</FormErrorFeedback>}
            </>
          )}
        />

        <Typography variant='overline'>Tiempo restante: {timeRemaining}</Typography>

        {!active && <Typography variant='overline'>El formulario ya ha finalizado</Typography>}
      </form>
    </>
  );
};

export default SurveyForm;