frontAnswerer/lib/components/QuizAnswerer.tsx
2025-06-15 12:58:15 +03:00

184 lines
6.0 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 { useQuizData } from "@/api/hooks";
import { QuizViewContext, createQuizViewStore } from "@/stores/quizView";
import LoadingSkeleton from "@/ui_kit/LoadingSkeleton";
import { useVkMetricsGoals } from "@/utils/hooks/metrics/useVkMetricsGoals";
import { useYandexMetricsGoals } from "@/utils/hooks/metrics/useYandexMetricsGoals";
import { RootContainerWidthContext } from "@contexts/RootContainerWidthContext";
import type { QuizSettings } from "@model/settingsData";
import { Box, CssBaseline, ScopedCssBaseline, ThemeProvider } from "@mui/material";
import { LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
import { ruRU } from "@mui/x-date-pickers/locales";
import { handleComponentError } from "@utils/handleComponentError";
import lightTheme from "@utils/themes/light";
import moment from "moment";
import { SnackbarProvider } from "notistack";
import { startTransition, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
import { ErrorBoundary } from "react-error-boundary";
import { ApologyPage } from "./ViewPublicationPage/ApologyPage";
import ViewPublicationPage from "./ViewPublicationPage/ViewPublicationPage";
import { HelmetProvider } from "react-helmet-async";
import "moment/dist/locale/ru";
import { useQuizStore, setQuizData, addquizid } from "@/stores/useQuizStore";
import { initDataManager } from "@/utils/hooks/useQuestionFlowControl";
moment.locale("ru");
const localeText = ruRU.components.MuiLocalizationProvider.defaultProps.localeText;
type Props = {
quizSettings?: QuizSettings;
quizId: string;
preview?: boolean;
changeFaviconAndTitle?: boolean;
className?: string;
disableGlobalCss?: boolean;
};
function QuizAnswererInner({
quizSettings,
quizId,
preview = false,
changeFaviconAndTitle = true,
className,
disableGlobalCss = false,
}: Props) {
const [quizViewStore] = useState(createQuizViewStore);
const [rootContainerWidth, setRootContainerWidth] = useState<number>(() => window.innerWidth);
const rootContainerRef = useRef<HTMLDivElement>(null);
const { data, error, isLoading } = useQuizData(quizId, preview);
const vkMetrics = useVkMetricsGoals(quizSettings?.settings.cfg.vkMetricsNumber);
const yandexMetrics = useYandexMetricsGoals(quizSettings?.settings.cfg.yandexMetricsNumber);
const r = useQuizStore();
const { settings, questions } = useQuizStore();
useEffect(() => {
addquizid(quizId);
}, []);
useEffect(() => {
console.log(settings);
console.log(questions);
console.log("r");
console.log(r);
}, [questions, settings]);
useEffect(() => {
setTimeout(() => {
vkMetrics.quizOpened();
yandexMetrics.quizOpened();
}, 4000);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
//Хук на случай если данные переданы нам сразу, а не "нам нужно их запросить"
if (quizSettings !== undefined) {
setQuizData(quizSettings);
initDataManager({
status: quizSettings.settings.status,
haveRoot: quizSettings.settings.cfg.haveRoot,
});
}
}, [quizSettings]);
useLayoutEffect(() => {
if (rootContainerRef.current) setRootContainerWidth(rootContainerRef.current.clientWidth);
}, []);
useEffect(() => {
const handleWindowResize = () => {
startTransition(() => {
if (rootContainerRef.current) setRootContainerWidth(rootContainerRef.current.clientWidth);
});
};
window.addEventListener("resize", handleWindowResize);
return () => {
window.removeEventListener("resize", handleWindowResize);
};
}, []);
console.log("settings");
console.log(settings);
if (isLoading) return <LoadingSkeleton />;
if (error) return <ApologyPage error={error} />;
if (Object.keys(settings).length == 0) return <ApologyPage error={new Error("quiz data is null")} />;
if (questions.length === 0) return <ApologyPage error={new Error("No questions found")} />;
if (questions.length === 1 && settings.cfg.noStartPage) return <ApologyPage error={new Error("quiz is empty")} />;
if (!quizId) return <ApologyPage error={new Error("no quiz id")} />;
const quizContainer = (
<Box
ref={rootContainerRef}
className={className}
sx={{
width: "100%",
height: "100%",
position: "relative",
}}
>
<ErrorBoundary
FallbackComponent={ApologyPage}
onError={handleComponentError}
>
<ViewPublicationPage />
</ErrorBoundary>
</Box>
);
return (
<QuizViewContext.Provider value={quizViewStore}>
<RootContainerWidthContext.Provider value={rootContainerWidth}>
{disableGlobalCss ? (
<ScopedCssBaseline
sx={{
height: "100%",
width: "100%",
backgroundColor: "transparent",
}}
>
{quizContainer}
</ScopedCssBaseline>
) : (
<CssBaseline>{quizContainer}</CssBaseline>
)}
</RootContainerWidthContext.Provider>
</QuizViewContext.Provider>
);
}
export default function QuizAnswerer(props: Props) {
return (
<HelmetProvider>
<LocalizationProvider
dateAdapter={AdapterMoment}
adapterLocale="ru"
localeText={localeText}
>
<ThemeProvider theme={lightTheme}>
<SnackbarProvider
preventDuplicate={true}
style={{ backgroundColor: lightTheme.palette.brightPurple.main }}
>
<Box
id="hideoverlay"
sx={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
background: "black",
zIndex: 999,
opacity: 0,
pointerEvents: "auto",
}}
/>
<QuizAnswererInner {...props} />
</SnackbarProvider>
</ThemeProvider>
</LocalizationProvider>
</HelmetProvider>
);
}