frontAnswerer/lib/components/ViewPublicationPage/ResultForm.tsx

402 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useEffect, useMemo } from "react";
import { Box, Button, Link, Typography, useTheme } from "@mui/material";
import { useQuizViewStore } from "@/stores/quizView";
import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
import { useVkMetricsGoals } from "@/utils/hooks/metrics/useVkMetricsGoals";
import { useYandexMetricsGoals } from "@/utils/hooks/metrics/useYandexMetricsGoals";
import { DESIGN_LIST } from "@/utils/designList";
import { quizThemes } from "@utils/themes/Publication/themePublication";
import { NameplateLogo } from "@icons/NameplateLogo";
import type { QuizQuestionResult } from "@/model/questionTypes/result";
import type { QuizQuestionVariant } from "@/model/questionTypes/variant";
import QuizVideo from "@/ui_kit/VideoIframe/VideoIframe";
import { TextAccordion } from "./tools/TextAccordion";
import { PointSystemResultList } from "./PointSystemResultList";
import { enqueueSnackbar } from "notistack";
import { sendFC, sendResult } from "@/api/quizRelase";
import { isProduction } from "@/utils/defineDomain";
import { useQuizStore } from "@/stores/useQuizStore";
import { useTranslation } from "react-i18next";
import { NameplateLogoDark } from "@/assets/icons/NameplateLogoDark";
type ResultFormProps = {
resultQuestion: QuizQuestionResult;
};
// Функция для определения вопроса "спасибо"
const isThankYouQuestion = (question: QuizQuestionVariant): boolean => {
// Проверяем что у вопроса только один вариант ответа
if (question.content.variants.length !== 1) {
return false;
}
// Проверяем что текст варианта полностью состоит из слова "спасибо"
const variant = question.content.variants[0];
const answerText = variant.answer.toLowerCase().trim();
// Проверяем точное совпадение со словом "спасибо"
return answerText === "спасибо";
};
export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
const theme = useTheme();
const isMobile = useRootContainerSize() < 650;
const isTablet = useRootContainerSize() < 1000;
const { settings, show_badge, quizId, questions, preview } = useQuizStore();
const setCurrentQuizStep = useQuizViewStore((state) => state.setCurrentQuizStep);
//Список засчитанных баллов для балловых квизов
const pointsSum = useQuizViewStore((state) => state.pointsSum);
const spec = settings.cfg.spec;
const vkMetrics = useVkMetricsGoals(settings.cfg.vkMetricsNumber);
const yandexMetrics = useYandexMetricsGoals(settings.cfg.yandexMetricsNumber);
const { t } = useTranslation();
// Проверяем, является ли это квизом с костылем
const dinocrutch = window.location.pathname === "/413b9e24-996a-400e-9076-c158f64b9bd7";
// Вычисляем общее количество вопросов с учетом фильтрации
const totalQuestions = useMemo(() => {
if (dinocrutch) {
// Для квиза с костылем: исключаем вопросы "спасибо" и вопросы типа "result"
const variantQuestions = questions.filter((e) => e.type === "variant") as QuizQuestionVariant[];
const filteredQuestions = variantQuestions.filter((q) => !isThankYouQuestion(q));
return filteredQuestions.length;
}
// Для обычных квизов: исключаем только вопросы типа "result"
return questions.filter((e) => e.type !== "result").length;
}, [questions, dinocrutch]);
useEffect(() => {
vkMetrics.resultIdShown(resultQuestion.id);
yandexMetrics.resultIdShown(resultQuestion.id);
}, [resultQuestion.id, vkMetrics, yandexMetrics]);
useEffect(() => {
(async () => {
if (!settings.cfg.showfc) {
try {
await sendFC({
questionId: resultQuestion.id,
body: {},
qid: quizId,
preview,
});
const sessions = JSON.parse(localStorage.getItem("sessions") || "{}");
localStorage.setItem("sessions", JSON.stringify({ ...sessions, [quizId]: new Date().getTime() }));
} catch (e) {
enqueueSnackbar(t("The request could not be sent"));
}
}
if (Boolean(settings.cfg.score)) {
try {
await sendResult({
questionId: resultQuestion.id,
pointsSum,
qid: quizId,
preview,
});
const sessions = JSON.parse(localStorage.getItem("sessions") || "{}");
localStorage.setItem("sessions", JSON.stringify({ ...sessions, [quizId]: new Date().getTime() }));
} catch (e) {
enqueueSnackbar(t("Количество баллов не может быть отправлено"));
}
}
})();
}, []);
const choiceImgUrlQuestion = useMemo(() => {
if (
resultQuestion.content.editedUrlImagesList !== undefined &&
resultQuestion.content.editedUrlImagesList !== null
) {
return resultQuestion.content.editedUrlImagesList[isMobile ? "mobile" : isTablet ? "tablet" : "desktop"];
} else {
return resultQuestion.content.back;
}
}, [resultQuestion]);
return (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "space-between",
height: "100%",
minHeight: "100%",
width: "100%",
backgroundColor: theme.palette.background.default,
backgroundPosition: "center",
backgroundSize: "cover",
backgroundImage: settings.cfg.design && !isMobile ? `url(${DESIGN_LIST[settings.cfg.theme]})` : null,
position: "relative",
}}
>
<Box
sx={{
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
alignItems: "center",
width: "100%",
height: "100%",
background:
settings.cfg.design && !isMobile
? quizThemes[settings.cfg.theme].isLight
? "transparent"
: "linear-gradient(90deg, rgba(39, 38, 38, 0.95) 7.66%, rgba(42, 42, 46, 0.85) 42.12%, rgba(51, 54, 71, 0.4) 100%)"
: theme.palette.background.default,
}}
>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
width: "100%",
height: "100%",
overflow: "auto",
padding: "0 20px 20px",
scrollbarWidth: "none",
"&::-webkit-scrollbar": {
width: 0,
},
}}
>
<Box
sx={{
display: "flex",
alignItems: "center",
flexWrap: "wrap",
mb: "10px",
width: "100%",
maxWidth: "700px",
backgroundColor: "#9A9AAF1A",
borderRadius: "0 0 12px 12px",
padding: "20px 20px 15px",
}}
>
<Typography
sx={{
fontSize: "17px",
color: "#9A9AAF",
wordBreak: "break-word",
}}
>
{t("Your result")}:
</Typography>
</Box>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
width: "100%",
maxWidth: "700px",
}}
>
{!resultQuestion?.content.useImage && resultQuestion.content.video && (
<QuizVideo
videoUrl={resultQuestion.content.video}
containerSX={{
width: "100%",
maxWidth: "700px",
height: isMobile ? "100%" : "306px",
}}
/>
)}
{resultQuestion?.content.useImage && choiceImgUrlQuestion && (
<Box
sx={{
width: "100%",
display: "flex",
justifyContent: "center",
}}
onClick={(event) => event.preventDefault()}
>
<img
alt="resultImage"
src={choiceImgUrlQuestion}
style={{
width: "100%",
height: spec ? "auto" : isMobile ? "236px" : "306px",
borderRadius: "12px",
objectFit: "cover",
overflow: "hidden",
}}
/>
</Box>
)}
{resultQuestion.description !== "" && resultQuestion.description !== " " && (
<Typography
sx={{
fontSize: "27px",
lineHeight: "32px",
fontWeight: 700,
mt: "30px",
color: theme.palette.text.primary,
wordBreak: "break-word",
}}
>
{resultQuestion.description}
</Typography>
)}
<Typography
sx={{
mt: "12px",
fontSize: "17px",
lineHeight: "20px",
color: theme.palette.text.primary,
wordBreak: "break-word",
}}
>
{resultQuestion.title}
</Typography>
{resultQuestion.content.text !== "" && resultQuestion.content.text !== " " && (
<Typography
sx={{
fontSize: "17px",
lineHeight: "20px",
mt: "25px ",
wordBreak: "break-word",
color: theme.palette.text.primary,
}}
>
{resultQuestion.content.text}
</Typography>
)}
{settings.cfg?.score && (
<>
<Typography
sx={{
color: theme.palette.primary.main,
fontSize: "30px",
m: "30px 0",
fontWeight: 600,
}}
>
{t("Your points")}
</Typography>
<Typography
sx={{
color: theme.palette.primary.main,
fontSize: "30px",
fontWeight: 600,
}}
>
{pointsSum} {t("of")} {totalQuestions}
</Typography>
<TextAccordion
headerText={
<Typography
sx={{
color: theme.palette.primary.main,
"&:hover": {
color: theme.palette.primary.dark,
},
}}
>
{t("View answers")}
</Typography>
}
sx={{
mt: "60px",
width: "100%",
}}
>
<Box
sx={{
mt: "25px",
}}
>
<PointSystemResultList />
</Box>
</TextAccordion>
</>
)}
</Box>
</Box>
{show_badge && (
<Box
component={Link}
target={"_blank"}
href={`https://${isProduction ? "" : "s"}quiz.pena.digital/answer/v1.0.0/logo?q=${quizId}`}
sx={{
display: "flex",
alignItems: "center",
alignSelf: isMobile ? "center" : "end",
margin: isMobile ? "15px 0 0" : "15px 25px 0 0",
gap: "10px",
textDecoration: "none",
mb: "15px",
position: isTablet || isMobile ? "sticky" : "absolute",
bottom: "90px",
}}
>
{quizThemes[settings.cfg.theme].isLight ? <NameplateLogoDark /> : <NameplateLogo />}
</Box>
)}
<Box
sx={{
width: "100%",
flexDirection: "column",
display: "flex",
justifyContent: "center",
alignItems: "center",
borderTop: "1px solid #9A9AAF80",
p: "20px",
position: "sticky",
bottom: 0,
}}
>
{settings.cfg.resultInfo.showResultForm === "before" &&
settings.cfg.showfc !== false &&
!settings.cfg.score && (
<Button
onClick={() => setCurrentQuizStep("contactform")}
variant="contained"
sx={{
p: "10px 20px",
width: "auto",
height: "50px",
}}
>
{resultQuestion.content.hint.text || t("Find out more")}
</Button>
)}
{settings.cfg.resultInfo.showResultForm === "after" && resultQuestion.content.redirect && (
<Button
onClick={() => {
vkMetrics.resultLink();
yandexMetrics.resultLink();
setTimeout(() => {
location.href = (
resultQuestion.content.redirect.includes("https")
? resultQuestion.content.redirect
: `https://${resultQuestion.content.redirect}`
).replace(/\s+/g, "");
}, 1000);
}}
variant="contained"
sx={{
p: "10px 20px",
width: "auto",
}}
>
{resultQuestion.content.hint.text || t("Go to website")}
</Button>
)}
</Box>
</Box>
</Box>
);
};