153 lines
4.9 KiB
TypeScript
153 lines
4.9 KiB
TypeScript
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 { useQuizSettings } from "@contexts/QuizDataContext";
|
||
import { ThemeProvider, Typography } from "@mui/material";
|
||
import { useQuizViewStore } from "@stores/quizView";
|
||
import { useQuestionFlowControl } from "@utils/hooks/useQuestionFlowControl";
|
||
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";
|
||
|
||
export default function ViewPublicationPage() {
|
||
const { settings, recentlyCompleted, quizId, preview, changeFaviconAndTitle } = useQuizSettings();
|
||
const answers = useQuizViewStore((state) => state.answers);
|
||
let currentQuizStep = useQuizViewStore((state) => state.currentQuizStep);
|
||
const {
|
||
currentQuestion,
|
||
currentQuestionStepNumber,
|
||
nextQuestion,
|
||
isNextButtonEnabled,
|
||
isPreviousButtonEnabled,
|
||
moveToPrevQuestion,
|
||
moveToNextQuestion,
|
||
showResultAfterContactForm,
|
||
setQuestion,
|
||
} = useQuestionFlowControl();
|
||
useYandexMetrics(settings?.cfg?.yandexMetricsNumber);
|
||
useVKMetrics(settings?.cfg?.vkMetricsNumber);
|
||
|
||
useEffect(
|
||
function setFaviconAndTitle() {
|
||
if (!changeFaviconAndTitle) return;
|
||
|
||
const link = document.querySelector('link[rel="icon"]');
|
||
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");
|
||
if (currentQuizStep === "startpage" && settings.cfg.noStartPage) currentQuizStep = "question";
|
||
|
||
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 (currentQuizStep) {
|
||
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={isNextButtonEnabled}
|
||
moveToNextQuestion={() => {
|
||
moveToNextQuestion();
|
||
|
||
if (preview) return;
|
||
|
||
sendQuestionAnswer(quizId, currentQuestion, currentAnswer)?.catch((e) => {
|
||
enqueueSnackbar("Ошибка при отправке ответа");
|
||
console.error("Error sending answer", e);
|
||
});
|
||
}}
|
||
/>
|
||
}
|
||
questionSelect={
|
||
<QuestionSelect
|
||
selectedQuestion={currentQuestion}
|
||
setQuestion={setQuestion}
|
||
/>
|
||
}
|
||
/>
|
||
);
|
||
break;
|
||
}
|
||
case "contactform": {
|
||
quizStepElement = (
|
||
<ContactForm
|
||
currentQuestion={currentQuestion}
|
||
onShowResult={showResultAfterContactForm}
|
||
/>
|
||
);
|
||
break;
|
||
}
|
||
default:
|
||
notReachable(currentQuizStep);
|
||
}
|
||
|
||
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>
|
||
);
|
||
}
|