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;