frontAnswerer/lib/components/ViewPublicationPage/ViewPublicationPage.tsx

190 lines
6.5 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 { ContactForm } from "@/components/ViewPublicationPage/ContactForm/ContactForm.tsx";
import { extractImageLinksFromQuestion } from "@/utils/extractImageLinks";
import { useVKMetrics } from "@/utils/hooks/metrics/useVKMetrics";
import { useYandexMetrics } from "@/utils/hooks/metrics/useYandexMetrics";
import { sendQuestionAnswer } from "@/utils/sendQuestionAnswer";
import { ThemeProvider, Typography } from "@mui/material";
import { useQuizViewStore } from "@stores/quizView";
import { statusOfQuiz, useQuestionFlowControl } from "@utils/hooks/useQuestionFlowControl";
import { QuizStep } from "@/model/settingsData";
import { notReachable } from "@utils/notReachable";
import { quizThemes } from "@utils/themes/Publication/themePublication";
import { enqueueSnackbar } from "notistack";
import { ReactElement, useEffect } from "react";
import { Helmet } from "react-helmet-async";
import { Question } from "./Question";
import QuestionSelect from "./QuestionSelect";
import { ResultForm } from "./ResultForm";
import { StartPageViewPublication } from "./StartPageViewPublication";
import NextButton from "./tools/NextButton";
import PrevButton from "./tools/PrevButton";
import unscreen from "@/ui_kit/unscreen";
import { changeNextLoading, useQuizStore } from "@/stores/useQuizStore";
import { polyfillCountryFlagEmojis } from "country-flag-emoji-polyfill";
polyfillCountryFlagEmojis();
export default function ViewPublicationPage() {
const { settings, recentlyCompleted, quizId, preview, changeFaviconAndTitle } = useQuizStore();
const answers = useQuizViewStore((state) => state.answers);
const ownVariants = useQuizViewStore((state) => state.ownVariants);
const currentQuizStep = useQuizViewStore((state) => state.currentQuizStep);
const setCurrentQuizStep = useQuizViewStore((state) => state.setCurrentQuizStep);
const {
currentQuestion,
currentQuestionStepNumber,
nextQuestion,
isNextButtonEnabled,
isPreviousButtonEnabled,
moveToPrevQuestion,
moveToNextQuestion,
showResultAfterContactForm,
setQuestion,
} = useQuestionFlowControl();
useYandexMetrics(settings?.cfg?.yandexMetricsNumber, preview);
useVKMetrics(settings?.cfg?.vkMetricsNumber, preview);
useEffect(() => {
const root = document.getElementById("root");
const overlay = document.getElementById("hideoverlay");
if (!settings.cfg?.isUnSc) overlay?.remove();
if (root !== null && overlay !== null && settings.cfg?.isUnSc) {
unscreen(overlay, root);
}
}, []);
useEffect(
function setFaviconAndTitle() {
if (!changeFaviconAndTitle) {
return;
}
const link = document.querySelector('link[rel="icon"]');
// Для localhost:5173 устанавливаем фавиконку из настроек квиза
if (window.location.hostname === "localhost" && window.location.port === "5173") {
if (link && settings.cfg.startpage.favIcon) {
link.setAttribute("href", settings.cfg.startpage.favIcon);
}
} else if (link && settings.cfg.startpage.favIcon) {
link.setAttribute("href", settings.cfg.startpage.favIcon);
}
document.title = settings.name;
},
[changeFaviconAndTitle, settings.cfg.startpage.favIcon, settings.name]
);
if (settings.cfg.antifraud && recentlyCompleted) throw new Error("Quiz already completed");
// Обработка noStartPage - обновляем состояние в store
useEffect(() => {
if (currentQuizStep === "startpage" && settings.cfg.noStartPage) {
setCurrentQuizStep("question");
}
}, [currentQuizStep, settings.cfg.noStartPage, setCurrentQuizStep]);
// Определяем текущий шаг для рендеринга
const displayQuizStep: QuizStep =
currentQuizStep === "startpage" && settings.cfg.noStartPage ? "question" : currentQuizStep;
if (!currentQuestion) {
return (
<ThemeProvider theme={quizThemes[settings.cfg.theme || "StandardTheme"].theme}>
<Typography
textAlign={"center"}
mt="50px"
>
Вопрос не выбран
</Typography>
</ThemeProvider>
);
}
const currentAnswer = answers.find(({ questionId }) => questionId === currentQuestion.id);
let quizStepElement: ReactElement;
switch (displayQuizStep) {
case "startpage": {
quizStepElement = <StartPageViewPublication />;
break;
}
case "question": {
if (currentQuestion.type === "result") {
quizStepElement = <ResultForm resultQuestion={currentQuestion} />;
break;
}
quizStepElement = (
<Question
key={currentQuestion.id}
currentQuestion={currentQuestion}
currentQuestionStepNumber={currentQuestionStepNumber}
prevButton={
<PrevButton
isPreviousButtonEnabled={isPreviousButtonEnabled}
moveToPrevQuestion={moveToPrevQuestion}
/>
}
nextButton={
<NextButton
isNextButtonEnabled={settings.status === "ai" || isNextButtonEnabled}
moveToNextQuestion={async () => {
if (statusOfQuiz == "ai") changeNextLoading(true);
if (!preview) {
await sendQuestionAnswer(quizId, currentQuestion, currentAnswer, ownVariants)?.catch((e) => {
enqueueSnackbar("Ошибка при отправке ответа");
console.error("Error sending answer", e);
});
}
moveToNextQuestion();
}}
/>
}
questionSelect={
<QuestionSelect
selectedQuestion={currentQuestion}
setQuestion={setQuestion}
/>
}
/>
);
break;
}
case "contactform": {
quizStepElement = (
<ContactForm
currentQuestion={currentQuestion}
onShowResult={showResultAfterContactForm}
/>
);
break;
}
default:
notReachable(displayQuizStep);
}
const preloadLinks = new Set([
...extractImageLinksFromQuestion(currentQuestion),
...extractImageLinksFromQuestion(nextQuestion),
]);
return (
<ThemeProvider theme={quizThemes[settings.cfg.theme || "StandardTheme"].theme}>
<Helmet>
{Array.from(preloadLinks).map((link) => (
<link
key={link}
rel="preload"
as="image"
href={link}
/>
))}
</Helmet>
{quizStepElement}
</ThemeProvider>
);
}