Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 3081 | 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, LockClock } from "@mui/icons-material";

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

import Widget from "@components/UI/Widget";
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 (
    <Widget>
      <Widget.Body>
        <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>
      </Widget.Body>
    </Widget>
  );
};

export default SurveyForm;