frontAnswerer/lib/components/QuizAnswerer.tsx
2025-08-12 04:26:22 +03:00

229 lines
7.9 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, statusOfQuiz } from "@/utils/hooks/useQuestionFlowControl";
console.log("🚀 QuizAnswerer: Component module loaded");
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) {
console.log("🔧 QuizAnswererInner: Component function called with props:", {
quizId,
preview,
changeFaviconAndTitle,
disableGlobalCss,
});
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();
console.log("🔍 QuizAnswererInner: Component state initialized");
useEffect(() => {
console.log("🔧 QuizAnswererInner: addquizid effect triggered");
addquizid(quizId);
}, []);
useEffect(() => {
console.log("🔍 QuizAnswererInner: Debug effect - settings:", settings);
console.log("🔍 QuizAnswererInner: Debug effect - questions:", questions);
console.log("🔍 QuizAnswererInner: Debug effect - r:", r);
}, [questions, settings]);
useEffect(() => {
console.log("🔧 QuizAnswererInner: Metrics effect triggered");
setTimeout(() => {
vkMetrics.quizOpened();
yandexMetrics.quizOpened();
}, 4000);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
//Хук на случай если данные переданы нам сразу, а не "нам нужно их запросить"
if (quizSettings !== undefined) {
console.log("🔧 QuizAnswererInner: setQuizData effect triggered with quizSettings");
setQuizData(quizSettings);
initDataManager({
status: quizSettings.settings.status,
haveRoot: quizSettings.settings.cfg.haveRoot,
});
}
}, [quizSettings]);
useLayoutEffect(() => {
console.log("🔧 QuizAnswererInner: Layout effect triggered");
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("🔍 QuizAnswererInner: About to render, current state:");
console.log("🔍 QuizAnswererInner: isLoading:", isLoading);
console.log("🔍 QuizAnswererInner: error:", error);
console.log("🔍 QuizAnswererInner: settings keys count:", Object.keys(settings).length);
console.log("🔍 QuizAnswererInner: questions length:", questions.length);
console.log("settings");
console.log(settings);
if (isLoading && !questions.length) {
console.log("🔍 QuizAnswererInner: Rendering LoadingSkeleton");
return <LoadingSkeleton />;
}
console.log("error");
console.log(error);
if (error) {
console.log("🔍 QuizAnswererInner: Rendering ApologyPage due to error");
return <ApologyPage error={error} />;
}
if (Object.keys(settings).length == 0) {
console.log("🔍 QuizAnswererInner: Rendering ApologyPage due to empty settings");
return <ApologyPage error={new Error("quiz data is null")} />;
}
if (questions.length === 0) {
console.log("🔍 QuizAnswererInner: Rendering ApologyPage due to no questions");
return <ApologyPage error={new Error("No questions found")} />;
}
if (questions.length === 1 && settings.cfg.noStartPage && statusOfQuiz != "ai") {
console.log("🔍 QuizAnswererInner: Rendering ApologyPage due to quiz is empty");
return <ApologyPage error={new Error("quiz is empty")} />;
}
if (!quizId) {
console.log("🔍 QuizAnswererInner: Rendering ApologyPage due to no quiz id");
return <ApologyPage error={new Error("no quiz id")} />;
}
console.log("🔍 QuizAnswererInner: Rendering main quiz container");
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) {
console.log("🔧 QuizAnswerer: Main component function called with 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>
);
}