Merge branch 'dev' into 'staging'
Dev See merge request frontend/squzanswerer!93
BIN
lib/assets/icons/PenaLogo.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
lib/assets/icons/designs/design1.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
lib/assets/icons/designs/design10.jpg
Normal file
|
After Width: | Height: | Size: 692 KiB |
BIN
lib/assets/icons/designs/design2.jpg
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
lib/assets/icons/designs/design3.jpg
Normal file
|
After Width: | Height: | Size: 599 KiB |
BIN
lib/assets/icons/designs/design4.jpg
Normal file
|
After Width: | Height: | Size: 719 KiB |
BIN
lib/assets/icons/designs/design5.jpg
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
lib/assets/icons/designs/design6.jpg
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
lib/assets/icons/designs/design7.jpg
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
lib/assets/icons/designs/design8.jpg
Normal file
|
After Width: | Height: | Size: 303 KiB |
BIN
lib/assets/icons/designs/design9.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
@ -16,6 +16,7 @@ import { quizThemes } from "@utils/themes/Publication/themePublication";
|
|||||||
import { enqueueSnackbar } from "notistack";
|
import { enqueueSnackbar } from "notistack";
|
||||||
import { useRootContainerSize } from "../../contexts/RootContainerWidthContext";
|
import { useRootContainerSize } from "../../contexts/RootContainerWidthContext";
|
||||||
import { useQuizData } from "@contexts/QuizDataContext";
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
|
import { DESIGN_LIST } from "@/components/ViewPublicationPage/Question";
|
||||||
|
|
||||||
|
|
||||||
const TextField = MuiTextField as unknown as FC<TextFieldProps>; // temporary fix ts(2590)
|
const TextField = MuiTextField as unknown as FC<TextFieldProps>; // temporary fix ts(2590)
|
||||||
@ -153,6 +154,11 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
|
|||||||
},
|
},
|
||||||
scrollbarWidth: "none",
|
scrollbarWidth: "none",
|
||||||
msOverflowStyle: "none",
|
msOverflowStyle: "none",
|
||||||
|
backgroundPosition: "center",
|
||||||
|
backgroundSize: "cover",
|
||||||
|
backgroundImage: settings.cfg.design
|
||||||
|
? `url(${DESIGN_LIST[settings.cfg.theme]})`
|
||||||
|
: null,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
@ -160,6 +166,7 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
|
|||||||
width: isWide && !isMobile ? "100%" : isMobile ? undefined : "530px",
|
width: isWide && !isMobile ? "100%" : isMobile ? undefined : "530px",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
|
minHeight: "100vh",
|
||||||
display: isWide && !isMobile ? "flex" : undefined,
|
display: isWide && !isMobile ? "flex" : undefined,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -238,6 +245,13 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
|
|||||||
disabled={!(ready && !fire)}
|
disabled={!(ready && !fire)}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={handleShowResultsClick}
|
onClick={handleShowResultsClick}
|
||||||
|
sx={{
|
||||||
|
border: `1px solid ${theme.palette.primary.main}`,
|
||||||
|
"&:disabled": {
|
||||||
|
border: "1px solid #9A9AAF",
|
||||||
|
color: "#9A9AAF"
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{settings.cfg.formContact?.button || "Получить результаты"}
|
{settings.cfg.formContact?.button || "Получить результаты"}
|
||||||
</Button>
|
</Button>
|
||||||
@ -416,6 +430,9 @@ const CustomInput = ({ title, desc, Icon, onChange, id }: {
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
sx={{
|
sx={{
|
||||||
width: isMobile ? "300px" : "350px",
|
width: isMobile ? "300px" : "350px",
|
||||||
|
"& .MuiOutlinedInput-notchedOutline": {
|
||||||
|
borderColor: "#9A9AAF"
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
placeholder={desc}
|
placeholder={desc}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
|
|||||||
@ -1,88 +1,71 @@
|
|||||||
import { useQuizData } from "@contexts/QuizDataContext";
|
|
||||||
import { Box, Typography, useTheme } from "@mui/material";
|
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
import { Box, Typography, useTheme } from "@mui/material";
|
||||||
|
|
||||||
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
|
|
||||||
|
import Stepper from "@ui_kit/Stepper";
|
||||||
|
|
||||||
type FooterProps = {
|
type FooterProps = {
|
||||||
stepNumber: number | null;
|
stepNumber: number | null;
|
||||||
nextButton: ReactNode;
|
nextButton: ReactNode;
|
||||||
prevButton: ReactNode;
|
prevButton: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Footer = ({ stepNumber, nextButton, prevButton }: FooterProps) => {
|
export const Footer = ({ stepNumber, nextButton, prevButton }: FooterProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { questions } = useQuizData();
|
const { questions, settings } = useQuizData();
|
||||||
console.log(questions)
|
const questionsAmount = questions.filter(
|
||||||
|
({ type }) => type !== "result"
|
||||||
|
).length;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: "relative",
|
||||||
|
padding: "15px 0",
|
||||||
|
borderTop: `1px solid ${theme.palette.grey[400]}`,
|
||||||
|
height: "75px",
|
||||||
|
display: "flex",
|
||||||
|
background: settings.cfg.design
|
||||||
|
? "rgba(154,154,175, 0.2)"
|
||||||
|
: "transparent",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
maxWidth: "1410px",
|
||||||
|
padding: "10px",
|
||||||
|
margin: "0 auto",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/*{mode[settings.cfg.theme] ? (*/}
|
||||||
|
{/* <NameplateLogoFQ style={{ fontSize: "34px", width:"200px", height:"auto" }} />*/}
|
||||||
|
{/*):(*/}
|
||||||
|
{/* <NameplateLogoFQDark style={{ fontSize: "34px", width:"200px", height:"auto" }} />*/}
|
||||||
|
{/*)}*/}
|
||||||
|
{stepNumber !== null && (
|
||||||
|
<Box sx={{ flexGrow: 1 }}>
|
||||||
|
<Typography sx={{ color: theme.palette.text.primary }}>
|
||||||
|
Вопрос {stepNumber} из {questionsAmount}
|
||||||
|
</Typography>
|
||||||
|
<Stepper activeStep={stepNumber} steps={questionsAmount} />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
return (
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
position: "relative",
|
display: "flex",
|
||||||
padding: "15px 0",
|
alignItems: "center",
|
||||||
borderTop: `1px solid ${theme.palette.grey[400]}`,
|
gap: "10px",
|
||||||
height: '75px',
|
marginRight: "auto",
|
||||||
display: "flex",
|
// color: theme.palette.grey1.main,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
{/* <Typography>Шаг</Typography>
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
maxWidth: "1000px",
|
|
||||||
padding: "0 10px",
|
|
||||||
margin: "0 auto",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "10px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{/*{mode[settings.cfg.theme] ? (*/}
|
|
||||||
{/* <NameplateLogoFQ style={{ fontSize: "34px", width:"200px", height:"auto" }} />*/}
|
|
||||||
{/*):(*/}
|
|
||||||
{/* <NameplateLogoFQDark style={{ fontSize: "34px", width:"200px", height:"auto" }} />*/}
|
|
||||||
{/*)}*/}
|
|
||||||
{stepNumber !== null &&
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "10px",
|
|
||||||
marginRight: "auto",
|
|
||||||
color: theme.palette.text.primary,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography>Шаг</Typography>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
fontWeight: "bold",
|
|
||||||
borderRadius: "50%",
|
|
||||||
width: "30px",
|
|
||||||
height: "30px",
|
|
||||||
color: "#FFF",
|
|
||||||
background: theme.palette.primary.main,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{stepNumber}
|
|
||||||
</Typography>
|
|
||||||
<Typography>Из</Typography>
|
|
||||||
<Typography sx={{ fontWeight: "bold" }}>
|
|
||||||
{questions.filter(q => q.type !== "result").length}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "10px",
|
|
||||||
marginRight: "auto",
|
|
||||||
// color: theme.palette.grey1.main,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{/* <Typography>Шаг</Typography>
|
|
||||||
<Typography
|
<Typography
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@ -97,15 +80,15 @@ export const Footer = ({ stepNumber, nextButton, prevButton }: FooterProps) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{stepNumber} */}
|
{stepNumber} */}
|
||||||
{/* </Typography> */}
|
{/* </Typography> */}
|
||||||
{/* <Typography>Из</Typography>
|
{/* <Typography>Из</Typography>
|
||||||
<Typography sx={{ fontWeight: "bold" }}>
|
<Typography sx={{ fontWeight: "bold" }}>
|
||||||
{questions.length}
|
{questions.length}
|
||||||
</Typography> */}
|
</Typography> */}
|
||||||
</Box>
|
|
||||||
{prevButton}
|
|
||||||
{nextButton}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
{prevButton}
|
||||||
|
{nextButton}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -20,78 +20,154 @@ import { NameplateLogoFQ } from "@icons/NameplateLogoFQ";
|
|||||||
import { NameplateLogoFQDark } from "@icons/NameplateLogoFQDark";
|
import { NameplateLogoFQDark } from "@icons/NameplateLogoFQDark";
|
||||||
import { notReachable } from "@utils/notReachable";
|
import { notReachable } from "@utils/notReachable";
|
||||||
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
import { ReactNode } from "react";
|
|
||||||
|
import Desgin1 from "@icons/designs/design1.jpg";
|
||||||
|
import Desgin2 from "@icons/designs/design2.jpg";
|
||||||
|
import Desgin3 from "@icons/designs/design3.jpg";
|
||||||
|
import Desgin4 from "@icons/designs/design4.jpg";
|
||||||
|
import Desgin5 from "@icons/designs/design5.jpg";
|
||||||
|
import Desgin6 from "@icons/designs/design6.jpg";
|
||||||
|
import Desgin7 from "@icons/designs/design7.jpg";
|
||||||
|
import Desgin8 from "@icons/designs/design8.jpg";
|
||||||
|
import Desgin9 from "@icons/designs/design9.jpg";
|
||||||
|
import Desgin10 from "@icons/designs/design10.jpg";
|
||||||
|
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
import type { QuizTheme } from "@model/settingsData";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
currentQuestion: RealTypedQuizQuestion;
|
currentQuestion: RealTypedQuizQuestion;
|
||||||
currentQuestionStepNumber: number | null;
|
currentQuestionStepNumber: number | null;
|
||||||
nextButton: ReactNode;
|
nextButton: ReactNode;
|
||||||
prevButton: ReactNode;
|
prevButton: ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DESIGN_LIST: Record<QuizTheme, string> = {
|
||||||
|
Design1: Desgin1,
|
||||||
|
Design2: Desgin2,
|
||||||
|
Design3: Desgin3,
|
||||||
|
Design4: Desgin4,
|
||||||
|
Design5: Desgin5,
|
||||||
|
Design6: Desgin6,
|
||||||
|
Design7: Desgin7,
|
||||||
|
Design8: Desgin8,
|
||||||
|
Design9: Desgin9,
|
||||||
|
Design10: Desgin10,
|
||||||
|
StandardTheme: "",
|
||||||
|
StandardDarkTheme: "",
|
||||||
|
PinkTheme: "",
|
||||||
|
PinkDarkTheme: "",
|
||||||
|
BlackWhiteTheme: "",
|
||||||
|
OliveTheme: "",
|
||||||
|
YellowTheme: "",
|
||||||
|
GoldDarkTheme: "",
|
||||||
|
PurpleTheme: "",
|
||||||
|
BlueTheme: "",
|
||||||
|
BlueDarkTheme: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Question = ({
|
export const Question = ({
|
||||||
currentQuestion,
|
currentQuestion,
|
||||||
currentQuestionStepNumber,
|
currentQuestionStepNumber,
|
||||||
nextButton,
|
nextButton,
|
||||||
prevButton,
|
prevButton,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { settings, show_badge } = useQuizData();
|
const { settings, show_badge } = useQuizData();
|
||||||
console.log(currentQuestionStepNumber)
|
|
||||||
return (
|
|
||||||
<Box sx={{
|
|
||||||
backgroundColor: theme.palette.background.default,
|
|
||||||
height: "100%",
|
|
||||||
}}>
|
|
||||||
<Box sx={{
|
|
||||||
height: "calc(100% - 75px)",
|
|
||||||
width: "100%",
|
|
||||||
maxWidth: "1440px",
|
|
||||||
padding: "40px 25px 20px",
|
|
||||||
margin: "0 auto",
|
|
||||||
overflow: "auto",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "space-between"
|
|
||||||
}}>
|
|
||||||
<QuestionByType key={currentQuestion.id} question={currentQuestion} stepNumber={currentQuestionStepNumber} />
|
|
||||||
|
|
||||||
{show_badge ? (quizThemes[settings.cfg.theme].isLight ? (
|
return (
|
||||||
<Link target={"_blank"} href={"https://quiz.pena.digital"}>
|
<Box
|
||||||
<NameplateLogoFQ style={{ fontSize: "34px", width: "200px", height: "auto" }} />
|
sx={{
|
||||||
</Link>
|
backgroundPosition: "center",
|
||||||
) : (
|
backgroundSize: "cover",
|
||||||
<Link target={"_blank"} href={"https://quiz.pena.digital"}>
|
backgroundImage: settings.cfg.design
|
||||||
<NameplateLogoFQDark style={{ fontSize: "34px", width: "200px", height: "auto" }} />
|
? `url(${DESIGN_LIST[settings.cfg.theme]})`
|
||||||
</Link>
|
: null,
|
||||||
)) : <></>}
|
}}
|
||||||
|
>
|
||||||
</Box>
|
<Box
|
||||||
<Footer
|
sx={{
|
||||||
stepNumber={currentQuestionStepNumber}
|
background: settings.cfg.design
|
||||||
prevButton={prevButton}
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
nextButton={nextButton}
|
? "transparent"
|
||||||
/>
|
: "linear-gradient(90deg,#272626, transparent)"
|
||||||
|
: theme.palette.background.default,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
height: "calc(100% - 75px)",
|
||||||
|
width: "100%",
|
||||||
|
minHeight: "calc(100vh - 75px)",
|
||||||
|
maxWidth: "1440px",
|
||||||
|
padding: "40px 25px 20px",
|
||||||
|
margin: "0 auto",
|
||||||
|
overflow: "auto",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<QuestionByType
|
||||||
|
key={currentQuestion.id}
|
||||||
|
question={currentQuestion}
|
||||||
|
stepNumber={currentQuestionStepNumber}
|
||||||
|
/>
|
||||||
|
{show_badge && (
|
||||||
|
<Link target="_blank" href="https://quiz.pena.digital">
|
||||||
|
{quizThemes[settings.cfg.theme].isLight ? (
|
||||||
|
<NameplateLogoFQ
|
||||||
|
style={{ fontSize: "34px", width: "200px", height: "auto" }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<NameplateLogoFQDark
|
||||||
|
style={{ fontSize: "34px", width: "200px", height: "auto" }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
<Footer
|
||||||
|
stepNumber={currentQuestionStepNumber}
|
||||||
|
prevButton={prevButton}
|
||||||
|
nextButton={nextButton}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function QuestionByType({ question, stepNumber }: {
|
function QuestionByType({
|
||||||
question: RealTypedQuizQuestion;
|
question,
|
||||||
stepNumber: number | null;
|
stepNumber,
|
||||||
|
}: {
|
||||||
|
question: RealTypedQuizQuestion;
|
||||||
|
stepNumber: number | null;
|
||||||
}) {
|
}) {
|
||||||
switch (question.type) {
|
switch (question.type) {
|
||||||
case "variant": return <Variant currentQuestion={question} />;
|
case "variant":
|
||||||
case "images": return <Images currentQuestion={question} />;
|
return <Variant currentQuestion={question} />;
|
||||||
case "varimg": return <Varimg currentQuestion={question} />;
|
case "images":
|
||||||
case "emoji": return <Emoji currentQuestion={question} />;
|
return <Images currentQuestion={question} />;
|
||||||
case "text": return <Text currentQuestion={question} stepNumber={stepNumber}/>;
|
case "varimg":
|
||||||
case "select": return <Select currentQuestion={question} />;
|
return <Varimg currentQuestion={question} />;
|
||||||
case "date": return <Date currentQuestion={question} />;
|
case "emoji":
|
||||||
case "number": return <Number currentQuestion={question} />;
|
return <Emoji currentQuestion={question} />;
|
||||||
case "file": return <File currentQuestion={question} />;
|
case "text":
|
||||||
case "page": return <Page currentQuestion={question} />;
|
return <Text currentQuestion={question} stepNumber={stepNumber} />;
|
||||||
case "rating": return <Rating currentQuestion={question} />;
|
case "select":
|
||||||
default: notReachable(question);
|
return <Select currentQuestion={question} />;
|
||||||
}
|
case "date":
|
||||||
|
return <Date currentQuestion={question} />;
|
||||||
|
case "number":
|
||||||
|
return <Number currentQuestion={question} />;
|
||||||
|
case "file":
|
||||||
|
return <File currentQuestion={question} />;
|
||||||
|
case "page":
|
||||||
|
return <Page currentQuestion={question} />;
|
||||||
|
case "rating":
|
||||||
|
return <Rating currentQuestion={question} />;
|
||||||
|
default:
|
||||||
|
notReachable(question);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { quizThemes } from "@utils/themes/Publication/themePublication";
|
|||||||
import { useRootContainerSize } from "../../contexts/RootContainerWidthContext";
|
import { useRootContainerSize } from "../../contexts/RootContainerWidthContext";
|
||||||
import type { QuizQuestionResult } from "../../model/questionTypes/result";
|
import type { QuizQuestionResult } from "../../model/questionTypes/result";
|
||||||
import { setCurrentQuizStep } from "@stores/quizView";
|
import { setCurrentQuizStep } from "@stores/quizView";
|
||||||
|
import { DESIGN_LIST } from "@/components/ViewPublicationPage/Question";
|
||||||
|
|
||||||
type ResultFormProps = {
|
type ResultFormProps = {
|
||||||
resultQuestion: QuizQuestionResult;
|
resultQuestion: QuizQuestionResult;
|
||||||
@ -22,6 +22,7 @@ type ResultFormProps = {
|
|||||||
export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
|
export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
|
const isTablet = useRootContainerSize() < 1000;
|
||||||
const { settings, show_badge } = useQuizData();
|
const { settings, show_badge } = useQuizData();
|
||||||
const spec = settings.cfg.spec
|
const spec = settings.cfg.spec
|
||||||
|
|
||||||
@ -33,19 +34,26 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
|
minHeight: "100vh",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
pt: "28px",
|
pt: "28px",
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
backgroundColor: theme.palette.background.default,
|
backgroundColor: theme.palette.background.default,
|
||||||
}}
|
backgroundPosition: "center",
|
||||||
|
backgroundSize: "cover",
|
||||||
|
backgroundImage: settings.cfg.design
|
||||||
|
? `url(${DESIGN_LIST[settings.cfg.theme]})`
|
||||||
|
: null,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
alignItems: "start",
|
alignItems: "start",
|
||||||
width: isMobile ? "100%" : "490px",
|
maxWidth: "844px",
|
||||||
padding: isMobile ? "0 16px" : undefined,
|
width: "100%",
|
||||||
|
padding: isMobile ? "0 16px" : isTablet ? "0 78px" : undefined,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
@ -65,8 +73,10 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
|
|||||||
component="img"
|
component="img"
|
||||||
src={resultQuestion.content.back}
|
src={resultQuestion.content.back}
|
||||||
sx={{
|
sx={{
|
||||||
width: spec ? "100%" : isMobile ? "100%" : "490px",
|
width: "100%",
|
||||||
height: spec ? "auto" : isMobile ? "100%" : "280px",
|
maxWidth: "844px",
|
||||||
|
height: spec ? "auto" : isMobile ? "100%" : "306px",
|
||||||
|
borderRadius: "8px"
|
||||||
}}
|
}}
|
||||||
></Box>
|
></Box>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,497 +0,0 @@
|
|||||||
import { Box, Button, ButtonBase, Link, Paper, Typography, useTheme } from "@mui/material";
|
|
||||||
import { useUADevice } from "../../utils/hooks/useUADevice";
|
|
||||||
import { notReachable } from "../../utils/notReachable";
|
|
||||||
import YoutubeEmbedIframe from "./tools/YoutubeEmbedIframe";
|
|
||||||
|
|
||||||
import { NameplateLogo } from "@icons/NameplateLogo";
|
|
||||||
import { QuizStartpageAlignType, QuizStartpageType } from "@model/settingsData";
|
|
||||||
import { useQuizData } from "@contexts/QuizDataContext";
|
|
||||||
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
|
||||||
import { useRootContainerSize } from "../../contexts/RootContainerWidthContext";
|
|
||||||
import { setCurrentQuizStep } from "@stores/quizView";
|
|
||||||
|
|
||||||
|
|
||||||
export const StartPageViewPublication = () => {
|
|
||||||
const theme = useTheme();
|
|
||||||
const { settings, show_badge } = useQuizData();
|
|
||||||
const { isMobileDevice } = useUADevice();
|
|
||||||
const isMobile = useRootContainerSize() < 650;
|
|
||||||
const isTablet = useRootContainerSize() < 800;
|
|
||||||
|
|
||||||
const handleCopyNumber = () => {
|
|
||||||
navigator.clipboard.writeText(settings.cfg.info.phonenumber);
|
|
||||||
};
|
|
||||||
console.log(settings.cfg.startpage.background.type);
|
|
||||||
|
|
||||||
const background =
|
|
||||||
settings.cfg.startpage.background.type === "image" ? (
|
|
||||||
settings.cfg.startpage.background.desktop ? (
|
|
||||||
<img
|
|
||||||
src={settings.cfg.startpage.background.desktop}
|
|
||||||
alt=""
|
|
||||||
style={{
|
|
||||||
width: (isMobile || settings.cfg.startpageType === "expanded") ? "100%" : undefined,
|
|
||||||
height: "100%",
|
|
||||||
objectFit: "cover",
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : null
|
|
||||||
) : settings.cfg.startpage.background.type === "video" ? (
|
|
||||||
settings.cfg.startpage.background.video ? (
|
|
||||||
<YoutubeEmbedIframe
|
|
||||||
videoUrl={settings.cfg.startpage.background.video}
|
|
||||||
containerSX={{
|
|
||||||
width:
|
|
||||||
settings.cfg.startpageType === "centered"
|
|
||||||
? "550px"
|
|
||||||
: "100%",
|
|
||||||
height:
|
|
||||||
settings.cfg.startpageType === "centered"
|
|
||||||
? "275px"
|
|
||||||
: "100%",
|
|
||||||
borderRadius: settings.cfg.startpageType === "centered" ? "10px" : "0",
|
|
||||||
overflow: "hidden",
|
|
||||||
"& iframe": {
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
transform:
|
|
||||||
settings.cfg.startpageType === "centered"
|
|
||||||
? ""
|
|
||||||
: settings.cfg.startpageType === "expanded"
|
|
||||||
? "scale(1.5)"
|
|
||||||
: "scale(2.4)",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : null
|
|
||||||
) : null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Paper
|
|
||||||
className="settings-preview-draghandle"
|
|
||||||
sx={{
|
|
||||||
borderRadius: 0,
|
|
||||||
height: "100%",
|
|
||||||
width: "100%",
|
|
||||||
background:
|
|
||||||
settings.cfg.startpageType === "expanded" && !isMobile
|
|
||||||
? settings.cfg.startpage.position === "left"
|
|
||||||
? "linear-gradient(90deg,#272626,transparent)"
|
|
||||||
: settings.cfg.startpage.position === "center"
|
|
||||||
? "linear-gradient(180deg,transparent,#272626)"
|
|
||||||
: "linear-gradient(270deg,#272626,transparent)"
|
|
||||||
: theme.palette.background.default,
|
|
||||||
|
|
||||||
color: settings.cfg.startpageType === "expanded" ? "white" : "black",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<QuizPreviewLayoutByType
|
|
||||||
quizHeaderBlock={
|
|
||||||
<Box p={settings.cfg.startpageType === "standard" ? "" : "16px"}>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "20px",
|
|
||||||
mb: "7px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{settings.cfg.startpage.logo && (
|
|
||||||
<img
|
|
||||||
src={settings.cfg.startpage.logo}
|
|
||||||
style={{
|
|
||||||
height: "37px",
|
|
||||||
maxWidth: "43px",
|
|
||||||
objectFit: "cover",
|
|
||||||
}}
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontSize: "14px",
|
|
||||||
color: settings.cfg.startpageType === "expanded"
|
|
||||||
&& !isMobile ? "white" : theme.palette.text.primary,
|
|
||||||
wordBreak: "break-word"
|
|
||||||
}}
|
|
||||||
>{settings.cfg.info.orgname}</Typography>
|
|
||||||
</Box>
|
|
||||||
<Link mb="16px" href={settings.cfg.info.site}>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontSize: "16px",
|
|
||||||
color: theme.palette.primary.main,
|
|
||||||
overflow: "hidden",
|
|
||||||
textOverflow: "ellipsis",
|
|
||||||
whiteSpace: "nowrap",
|
|
||||||
maxWidth: isTablet ? "200px" : "300px"
|
|
||||||
}}>
|
|
||||||
{settings.cfg.info.site}
|
|
||||||
</Typography>
|
|
||||||
</Link>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
quizMainBlock={
|
|
||||||
<>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems:
|
|
||||||
settings.cfg.startpageType === "centered"
|
|
||||||
? "center"
|
|
||||||
: settings.cfg.startpageType === "expanded"
|
|
||||||
? settings.cfg.startpage.position === "center"
|
|
||||||
? "center"
|
|
||||||
: "start"
|
|
||||||
: "start",
|
|
||||||
mt: "28px",
|
|
||||||
width: "100%",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontWeight: "bold",
|
|
||||||
fontSize: "26px",
|
|
||||||
fontStyle: "normal",
|
|
||||||
fontStretch: "normal",
|
|
||||||
lineHeight: "1.2",
|
|
||||||
overflowWrap: "break-word",
|
|
||||||
width: "100%",
|
|
||||||
textAlign: settings.cfg.startpageType === "centered" || settings.cfg.startpage.position === "center" ? "center" : "-moz-initial",
|
|
||||||
color: settings.cfg.startpageType === "expanded" && !isMobile ? "white" : theme.palette.text.primary
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{settings.name}
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontSize: "16px",
|
|
||||||
m: "16px 0",
|
|
||||||
overflowWrap: "break-word",
|
|
||||||
width: "100%",
|
|
||||||
textAlign: settings.cfg.startpageType === "centered" || settings.cfg.startpage.position === "center" ? "center" : "-moz-initial",
|
|
||||||
color: settings.cfg.startpageType === "expanded" && !isMobile ? "white" : theme.palette.text.primary
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{settings.cfg.startpage.description}
|
|
||||||
</Typography>
|
|
||||||
<Box width={settings.cfg.startpageType === "standard" ? "100%" : "auto"}>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
sx={{
|
|
||||||
fontSize: "16px",
|
|
||||||
padding: "10px 15px",
|
|
||||||
width: settings.cfg.startpageType === "standard" ? "100%" : "auto",
|
|
||||||
}}
|
|
||||||
onClick={() => setCurrentQuizStep("question")}
|
|
||||||
>
|
|
||||||
{settings.cfg.startpage.button.trim() ? settings.cfg.startpage.button : "Пройти тест"}
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
mt: "46px",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
width: "100%",
|
|
||||||
flexDirection: "column"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box sx={{ maxWidth: isTablet ? "240px" : "300px", marginBottom: "10px", }}>
|
|
||||||
{settings.cfg.info.clickable ? (
|
|
||||||
isMobileDevice ? (
|
|
||||||
<Link href={`tel:${settings.cfg.info.phonenumber}`}>
|
|
||||||
<Typography sx={{ fontSize: "16px", color: theme.palette.primary.main }}>
|
|
||||||
{settings.cfg.info.phonenumber}
|
|
||||||
</Typography>
|
|
||||||
</Link>
|
|
||||||
) : (
|
|
||||||
<ButtonBase onClick={handleCopyNumber}>
|
|
||||||
<Typography sx={{ fontSize: "16px", color: theme.palette.primary.main }}>
|
|
||||||
{settings.cfg.info.phonenumber}
|
|
||||||
</Typography>
|
|
||||||
</ButtonBase>
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<Typography sx={{ fontSize: "16px", color: theme.palette.primary.main }}>
|
|
||||||
{settings.cfg.info.phonenumber}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
<Typography sx={{
|
|
||||||
width: "100%",
|
|
||||||
overflowWrap: "break-word",
|
|
||||||
fontSize: "12px",
|
|
||||||
textAlign: "end",
|
|
||||||
maxHeight: "120px",
|
|
||||||
overflow: "auto",
|
|
||||||
"&::-webkit-scrollbar": { width: 0 },
|
|
||||||
color:
|
|
||||||
settings.cfg.startpageType === "expanded" && !isMobile
|
|
||||||
? "white"
|
|
||||||
: theme.palette.text.primary,
|
|
||||||
}}>
|
|
||||||
{settings.cfg.info.law}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
{show_badge &&
|
|
||||||
<Box
|
|
||||||
component={Link}
|
|
||||||
target={"_blank"}
|
|
||||||
href={"https://quiz.pena.digital"}
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "15px",
|
|
||||||
textDecoration: "none"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<NameplateLogo style={{ fontSize: "34px", color: settings.cfg.startpageType === "expanded" && !isMobile ? "#FFFFFF" : (quizThemes[settings.cfg.theme].isLight ? "#151515" : "#FFFFFF") }} />
|
|
||||||
<Typography sx={{ fontSize: "20px", color: settings.cfg.startpageType === "expanded" && !isMobile ? "#F5F7FF" : (quizThemes[settings.cfg.theme].isLight ? "#4D4D4D" : "#F5F7FF"), whiteSpace: "nowrap", }}>
|
|
||||||
Сделано на PenaQuiz
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
backgroundBlock={background}
|
|
||||||
startpageType={settings.cfg.startpageType}
|
|
||||||
alignType={settings.cfg.startpage.position}
|
|
||||||
/>
|
|
||||||
</Paper>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function QuizPreviewLayoutByType({
|
|
||||||
quizHeaderBlock,
|
|
||||||
quizMainBlock,
|
|
||||||
backgroundBlock,
|
|
||||||
startpageType,
|
|
||||||
alignType,
|
|
||||||
}: {
|
|
||||||
quizHeaderBlock: JSX.Element;
|
|
||||||
quizMainBlock: JSX.Element;
|
|
||||||
backgroundBlock: JSX.Element | null;
|
|
||||||
startpageType: QuizStartpageType;
|
|
||||||
alignType: QuizStartpageAlignType;
|
|
||||||
}) {
|
|
||||||
const isMobile = useRootContainerSize() < 650;
|
|
||||||
|
|
||||||
function StartPageMobile() {
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column-reverse",
|
|
||||||
flexGrow: 1,
|
|
||||||
justifyContent: "flex-end",
|
|
||||||
height: "100%",
|
|
||||||
"&::-webkit-scrollbar": { width: 0 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "flex-start",
|
|
||||||
p: "25px",
|
|
||||||
height: "100%",
|
|
||||||
overflowY: "auto",
|
|
||||||
overflowX: "hidden",
|
|
||||||
"&::-webkit-scrollbar": {
|
|
||||||
width: "4px",
|
|
||||||
},
|
|
||||||
"&::-webkit-scrollbar-thumb": {
|
|
||||||
backgroundColor: "#b8babf",
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{quizHeaderBlock}
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
height: "80%",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
width: "100%"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{quizMainBlock}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{backgroundBlock}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (startpageType) {
|
|
||||||
case null:
|
|
||||||
case "standard": {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{isMobile ? (
|
|
||||||
<StartPageMobile />
|
|
||||||
) : (
|
|
||||||
<Box
|
|
||||||
id="pain"
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: alignType === "left" ? (isMobile ? "column-reverse" : "row") : "row-reverse",
|
|
||||||
flexGrow: 1,
|
|
||||||
justifyContent: isMobile ? "flex-end" : undefined,
|
|
||||||
height: "100%",
|
|
||||||
"&::-webkit-scrollbar": { width: 0 },
|
|
||||||
overflow: "auto"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: isMobile ? "100%" : "40%",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "flex-start",
|
|
||||||
p: "25px",
|
|
||||||
height: isMobile ? "80%" : undefined
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{quizHeaderBlock}
|
|
||||||
{quizMainBlock}
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: isMobile ? "100%" : "60%",
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{backgroundBlock}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</>
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
case "expanded": {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{isMobile ? (
|
|
||||||
<StartPageMobile />
|
|
||||||
) : (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
overflow: "auto",
|
|
||||||
position: "relative",
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: startpageAlignTypeToJustifyContent[alignType],
|
|
||||||
flexGrow: 1,
|
|
||||||
height: "100%",
|
|
||||||
"&::-webkit-scrollbar": { width: 0 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "40%",
|
|
||||||
position: "relative",
|
|
||||||
padding: "16px",
|
|
||||||
zIndex: 3,
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: alignType === "center" ? "center" : "start",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{quizHeaderBlock}
|
|
||||||
{quizMainBlock}
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
position: "absolute",
|
|
||||||
zIndex: -1,
|
|
||||||
left: 0,
|
|
||||||
top: 0,
|
|
||||||
height: "100%",
|
|
||||||
width: "100%",
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{backgroundBlock}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
case "centered": {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{isMobile ? (
|
|
||||||
<StartPageMobile />
|
|
||||||
) : (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
overflow: "auto",
|
|
||||||
padding: "16px",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "center",
|
|
||||||
height: "100%",
|
|
||||||
"&::-webkit-scrollbar": { width: 0 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{quizHeaderBlock}
|
|
||||||
{backgroundBlock && (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "60%",
|
|
||||||
height: "275px",
|
|
||||||
// overflow: "hidden",
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{backgroundBlock}
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
{quizMainBlock}
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
notReachable(startpageType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const startpageAlignTypeToJustifyContent: Record<QuizStartpageAlignType, "start" | "center" | "end"> = {
|
|
||||||
left: "start",
|
|
||||||
center: "center",
|
|
||||||
right: "end",
|
|
||||||
};
|
|
||||||
44
lib/components/ViewPublicationPage/StartPageViewPublication/QuizPreviewLayoutByType.tsx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { StartPageDesktop } from "./StartPageDesktop";
|
||||||
|
import { StartPageMobile } from "./StartPageMobile";
|
||||||
|
|
||||||
|
import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
|
||||||
|
|
||||||
|
import type {
|
||||||
|
QuizStartpageAlignType,
|
||||||
|
QuizStartpageType,
|
||||||
|
} from "@model/settingsData";
|
||||||
|
|
||||||
|
type QuizPreviewLayoutByTypeProps = {
|
||||||
|
quizHeaderBlock: JSX.Element;
|
||||||
|
quizMainBlock: JSX.Element;
|
||||||
|
backgroundBlock: JSX.Element | null;
|
||||||
|
startpageType: QuizStartpageType;
|
||||||
|
alignType: QuizStartpageAlignType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const QuizPreviewLayoutByType = ({
|
||||||
|
quizHeaderBlock,
|
||||||
|
quizMainBlock,
|
||||||
|
backgroundBlock,
|
||||||
|
startpageType,
|
||||||
|
alignType,
|
||||||
|
}: QuizPreviewLayoutByTypeProps) => {
|
||||||
|
const isMobile = useRootContainerSize() < 700;
|
||||||
|
|
||||||
|
return isMobile ? (
|
||||||
|
<StartPageMobile
|
||||||
|
quizHeaderBlock={quizHeaderBlock}
|
||||||
|
quizMainBlock={quizMainBlock}
|
||||||
|
backgroundBlock={backgroundBlock}
|
||||||
|
startpageType={startpageType}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<StartPageDesktop
|
||||||
|
alignType={alignType}
|
||||||
|
startpageType={startpageType}
|
||||||
|
quizHeaderBlock={quizHeaderBlock}
|
||||||
|
quizMainBlock={quizMainBlock}
|
||||||
|
backgroundBlock={backgroundBlock}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,214 @@
|
|||||||
|
import { Box } from "@mui/material";
|
||||||
|
|
||||||
|
import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
|
||||||
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
|
|
||||||
|
import { notReachable } from "@utils/notReachable";
|
||||||
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
|
import { DESIGN_LIST } from "@/components/ViewPublicationPage/Question";
|
||||||
|
|
||||||
|
import type {
|
||||||
|
QuizStartpageAlignType,
|
||||||
|
QuizStartpageType,
|
||||||
|
} from "@model/settingsData";
|
||||||
|
|
||||||
|
type StartPageDesktopProps = {
|
||||||
|
quizHeaderBlock: JSX.Element;
|
||||||
|
quizMainBlock: JSX.Element;
|
||||||
|
backgroundBlock: JSX.Element | null;
|
||||||
|
startpageType: QuizStartpageType;
|
||||||
|
alignType: QuizStartpageAlignType;
|
||||||
|
};
|
||||||
|
|
||||||
|
type LayoutProps = Omit<StartPageDesktopProps, "startpageType">;
|
||||||
|
|
||||||
|
const StandartLayout = ({
|
||||||
|
alignType,
|
||||||
|
quizHeaderBlock,
|
||||||
|
quizMainBlock,
|
||||||
|
backgroundBlock,
|
||||||
|
}: LayoutProps) => {
|
||||||
|
const { settings } = useQuizData();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
id="pain"
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: alignType === "left" ? "row" : "row-reverse",
|
||||||
|
minHeight: "100vh",
|
||||||
|
backgroundPosition: "center",
|
||||||
|
backgroundSize: "cover",
|
||||||
|
backgroundImage: settings.cfg.design
|
||||||
|
? `url(${DESIGN_LIST[settings.cfg.theme]})`
|
||||||
|
: null,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "40%",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "flex-start",
|
||||||
|
p: "25px",
|
||||||
|
background:
|
||||||
|
settings.cfg.design && !quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "linear-gradient(90deg,#272626,transparent)"
|
||||||
|
: null,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{quizHeaderBlock}
|
||||||
|
{quizMainBlock}
|
||||||
|
</Box>
|
||||||
|
{settings.cfg.startpage.background.desktop && (
|
||||||
|
<Box sx={{ width: "60%", overflow: "hidden" }}>{backgroundBlock}</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ExpandedLayout = ({
|
||||||
|
alignType,
|
||||||
|
quizHeaderBlock,
|
||||||
|
quizMainBlock,
|
||||||
|
backgroundBlock,
|
||||||
|
}: LayoutProps) => (
|
||||||
|
<Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
zIndex: 3,
|
||||||
|
minHeight: "100vh",
|
||||||
|
width: "40%",
|
||||||
|
padding: "16px",
|
||||||
|
margin:
|
||||||
|
alignType === "center"
|
||||||
|
? "0 auto"
|
||||||
|
: alignType === "left"
|
||||||
|
? "0"
|
||||||
|
: "0 0 0 auto",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
padding: "16px",
|
||||||
|
minHeight: "calc(100vh - 32px)",
|
||||||
|
position: "relative",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: alignType === "center" ? "center" : "start",
|
||||||
|
borderRight: alignType === "left" ? "1px solid #9A9AAF80" : null,
|
||||||
|
borderLeft: alignType === "right" ? "1px solid #9A9AAF80" : null,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{quizHeaderBlock}
|
||||||
|
{quizMainBlock}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
zIndex: -1,
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
height: "100%",
|
||||||
|
width: "100%",
|
||||||
|
overflow: "hidden",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{backgroundBlock}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
|
const CenteredLayout = ({
|
||||||
|
quizHeaderBlock,
|
||||||
|
quizMainBlock,
|
||||||
|
backgroundBlock,
|
||||||
|
}: LayoutProps) => {
|
||||||
|
const isTablet = useRootContainerSize() < 1100;
|
||||||
|
const { settings } = useQuizData();
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
overflow: "auto",
|
||||||
|
padding: "10px 25px 25px",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "center",
|
||||||
|
minHeight: "100vh",
|
||||||
|
backgroundPosition: "center",
|
||||||
|
backgroundSize: "cover",
|
||||||
|
backgroundImage: settings.cfg.design
|
||||||
|
? `url(${DESIGN_LIST[settings.cfg.theme]})`
|
||||||
|
: null,
|
||||||
|
"&::-webkit-scrollbar": { width: 0 },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{quizHeaderBlock}
|
||||||
|
{backgroundBlock && settings.cfg.startpage.background.desktop && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
maxWidth: "844px",
|
||||||
|
height: isTablet ? "530px" : "306px",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
"& > img": { width: "100%", borderRadius: "12px" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{backgroundBlock}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{quizMainBlock}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const StartPageDesktop = ({
|
||||||
|
quizHeaderBlock,
|
||||||
|
quizMainBlock,
|
||||||
|
backgroundBlock,
|
||||||
|
startpageType,
|
||||||
|
alignType,
|
||||||
|
}: StartPageDesktopProps) => {
|
||||||
|
switch (startpageType) {
|
||||||
|
case null:
|
||||||
|
case "standard": {
|
||||||
|
return (
|
||||||
|
<StandartLayout
|
||||||
|
alignType={alignType}
|
||||||
|
quizHeaderBlock={quizHeaderBlock}
|
||||||
|
quizMainBlock={quizMainBlock}
|
||||||
|
backgroundBlock={backgroundBlock}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
case "expanded": {
|
||||||
|
return (
|
||||||
|
<ExpandedLayout
|
||||||
|
alignType={alignType}
|
||||||
|
quizHeaderBlock={quizHeaderBlock}
|
||||||
|
quizMainBlock={quizMainBlock}
|
||||||
|
backgroundBlock={backgroundBlock}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
case "centered": {
|
||||||
|
return (
|
||||||
|
<CenteredLayout
|
||||||
|
alignType={alignType}
|
||||||
|
quizHeaderBlock={quizHeaderBlock}
|
||||||
|
quizMainBlock={quizMainBlock}
|
||||||
|
backgroundBlock={backgroundBlock}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
notReachable(startpageType);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,265 @@
|
|||||||
|
import { Box } from "@mui/material";
|
||||||
|
|
||||||
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
|
|
||||||
|
import { notReachable } from "@utils/notReachable";
|
||||||
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
|
import { DESIGN_LIST } from "@/components/ViewPublicationPage/Question";
|
||||||
|
|
||||||
|
import type { QuizStartpageType } from "@model/settingsData";
|
||||||
|
|
||||||
|
type StartPageMobileProps = {
|
||||||
|
quizHeaderBlock: JSX.Element;
|
||||||
|
quizMainBlock: JSX.Element;
|
||||||
|
backgroundBlock: JSX.Element | null;
|
||||||
|
startpageType: QuizStartpageType;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MobileLayoutProps = Omit<StartPageMobileProps, "startpageType">;
|
||||||
|
|
||||||
|
const StandartMobileLayout = ({
|
||||||
|
quizHeaderBlock,
|
||||||
|
quizMainBlock,
|
||||||
|
backgroundBlock,
|
||||||
|
}: MobileLayoutProps) => {
|
||||||
|
const { settings } = useQuizData();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column-reverse",
|
||||||
|
flexGrow: 1,
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
minHeight: "100vh",
|
||||||
|
height: "100%",
|
||||||
|
"&::-webkit-scrollbar": { width: 0 },
|
||||||
|
backgroundPosition: "center",
|
||||||
|
backgroundSize: "cover",
|
||||||
|
backgroundImage: settings.cfg.design
|
||||||
|
? `url(${DESIGN_LIST[settings.cfg.theme]})`
|
||||||
|
: null,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
flexGrow: 1,
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "flex-start",
|
||||||
|
p: "25px",
|
||||||
|
height: "100%",
|
||||||
|
overflowY: "auto",
|
||||||
|
overflowX: "hidden",
|
||||||
|
background:
|
||||||
|
settings.cfg.design && !quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "linear-gradient(90deg,#272626,transparent)"
|
||||||
|
: null,
|
||||||
|
"&::-webkit-scrollbar": {
|
||||||
|
width: "4px",
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb": {
|
||||||
|
backgroundColor: "#b8babf",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{quizHeaderBlock}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
height: "80%",
|
||||||
|
display: "flex",
|
||||||
|
flexGrow: 1,
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{quizMainBlock}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
{settings.cfg.startpage.background.desktop && (
|
||||||
|
<Box sx={{ width: "100%", overflow: "hidden" }}>{backgroundBlock}</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ExpandedMobileLayout = ({
|
||||||
|
quizHeaderBlock,
|
||||||
|
quizMainBlock,
|
||||||
|
backgroundBlock,
|
||||||
|
}: MobileLayoutProps) => (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column-reverse",
|
||||||
|
flexGrow: 1,
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
minHeight: "100vh",
|
||||||
|
height: "100%",
|
||||||
|
"&::-webkit-scrollbar": { width: 0 },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
zIndex: 3,
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
flexGrow: 1,
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "flex-start",
|
||||||
|
height: "100%",
|
||||||
|
overflowY: "auto",
|
||||||
|
overflowX: "hidden",
|
||||||
|
"&::-webkit-scrollbar": { width: "4px" },
|
||||||
|
"&::-webkit-scrollbar-thumb": { backgroundColor: "#b8babf" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{quizHeaderBlock}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
padding: "16px",
|
||||||
|
height: "80%",
|
||||||
|
display: "flex",
|
||||||
|
flexGrow: 1,
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{quizMainBlock}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
zIndex: -1,
|
||||||
|
position: "absolute",
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
width: "100%",
|
||||||
|
minHeight: "100vh",
|
||||||
|
overflow: "hidden",
|
||||||
|
"& > img": {
|
||||||
|
display: "block",
|
||||||
|
minHeight: "100vh",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{backgroundBlock}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
|
const CenteredMobileLayout = ({
|
||||||
|
quizHeaderBlock,
|
||||||
|
quizMainBlock,
|
||||||
|
backgroundBlock,
|
||||||
|
}: MobileLayoutProps) => {
|
||||||
|
const {settings} = useQuizData();
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column-reverse",
|
||||||
|
flexGrow: 1,
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
minHeight: "100vh",
|
||||||
|
height: "100%",
|
||||||
|
backgroundPosition: "center",
|
||||||
|
backgroundSize: "cover",
|
||||||
|
backgroundImage: settings.cfg.design
|
||||||
|
? `url(${DESIGN_LIST[settings.cfg.theme]})`
|
||||||
|
: null,
|
||||||
|
"&::-webkit-scrollbar": {width: 0},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
flexGrow: 1,
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "flex-start",
|
||||||
|
padding: "10px 25px 25px",
|
||||||
|
height: "100%",
|
||||||
|
overflowY: "auto",
|
||||||
|
overflowX: "hidden",
|
||||||
|
"&::-webkit-scrollbar": {width: "4px"},
|
||||||
|
"&::-webkit-scrollbar-thumb": {backgroundColor: "#b8babf"},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{quizHeaderBlock}
|
||||||
|
{settings.cfg.startpage.background.desktop && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
overflow: "hidden",
|
||||||
|
"& > img": {width: "100%", borderRadius: "12px"},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{backgroundBlock}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
height: "80%",
|
||||||
|
display: "flex",
|
||||||
|
flexGrow: 1,
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{quizMainBlock}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const StartPageMobile = ({
|
||||||
|
quizHeaderBlock,
|
||||||
|
quizMainBlock,
|
||||||
|
backgroundBlock,
|
||||||
|
startpageType,
|
||||||
|
}: StartPageMobileProps) => {
|
||||||
|
switch (startpageType) {
|
||||||
|
case null:
|
||||||
|
case "standard": {
|
||||||
|
return (
|
||||||
|
<StandartMobileLayout
|
||||||
|
quizHeaderBlock={quizHeaderBlock}
|
||||||
|
quizMainBlock={quizMainBlock}
|
||||||
|
backgroundBlock={backgroundBlock}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
case "expanded": {
|
||||||
|
return (
|
||||||
|
<ExpandedMobileLayout
|
||||||
|
quizHeaderBlock={quizHeaderBlock}
|
||||||
|
quizMainBlock={quizMainBlock}
|
||||||
|
backgroundBlock={backgroundBlock}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
case "centered": {
|
||||||
|
return (
|
||||||
|
<CenteredMobileLayout
|
||||||
|
quizHeaderBlock={quizHeaderBlock}
|
||||||
|
quizMainBlock={quizMainBlock}
|
||||||
|
backgroundBlock={backgroundBlock}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
notReachable(startpageType);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,374 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
ButtonBase,
|
||||||
|
Link,
|
||||||
|
Paper,
|
||||||
|
Typography,
|
||||||
|
useTheme,
|
||||||
|
} from "@mui/material";
|
||||||
|
|
||||||
|
import { QuizPreviewLayoutByType } from "./QuizPreviewLayoutByType";
|
||||||
|
import YoutubeEmbedIframe from "../tools/YoutubeEmbedIframe";
|
||||||
|
|
||||||
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
|
import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
|
||||||
|
import { setCurrentQuizStep } from "@stores/quizView";
|
||||||
|
|
||||||
|
import { useUADevice } from "@utils/hooks/useUADevice";
|
||||||
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
|
|
||||||
|
import { DESIGN_LIST } from "../Question";
|
||||||
|
|
||||||
|
import { NameplateLogo } from "@icons/NameplateLogo";
|
||||||
|
import PenaLogo from "@icons/PenaLogo.png";
|
||||||
|
|
||||||
|
export const StartPageViewPublication = () => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const { settings, show_badge } = useQuizData();
|
||||||
|
const { isMobileDevice } = useUADevice();
|
||||||
|
const isMobile = useRootContainerSize() < 700;
|
||||||
|
const isTablet = useRootContainerSize() < 800;
|
||||||
|
|
||||||
|
const handleCopyNumber = () => {
|
||||||
|
navigator.clipboard.writeText(settings.cfg.info.phonenumber);
|
||||||
|
};
|
||||||
|
|
||||||
|
const background =
|
||||||
|
settings.cfg.startpage.background.type === "image" ? (
|
||||||
|
<img
|
||||||
|
src={
|
||||||
|
settings.cfg.startpage.background.desktop ||
|
||||||
|
DESIGN_LIST[settings.cfg.theme] ||
|
||||||
|
""
|
||||||
|
}
|
||||||
|
alt=""
|
||||||
|
style={{
|
||||||
|
display: "block",
|
||||||
|
width:
|
||||||
|
isMobile || settings.cfg.startpageType === "expanded"
|
||||||
|
? "100%"
|
||||||
|
: undefined,
|
||||||
|
height: "100%",
|
||||||
|
minWidth: "100%",
|
||||||
|
maxHeight: "100vh",
|
||||||
|
objectFit: "cover",
|
||||||
|
overflow: "hidden",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : settings.cfg.startpage.background.type === "video" ? (
|
||||||
|
settings.cfg.startpage.background.video ? (
|
||||||
|
<YoutubeEmbedIframe
|
||||||
|
videoUrl={settings.cfg.startpage.background.video}
|
||||||
|
containerSX={{
|
||||||
|
width: settings.cfg.startpageType === "centered" ? "550px" : "100%",
|
||||||
|
height:
|
||||||
|
settings.cfg.startpageType === "centered" ? "275px" : "100%",
|
||||||
|
borderRadius:
|
||||||
|
settings.cfg.startpageType === "centered" ? "10px" : "0",
|
||||||
|
overflow: "hidden",
|
||||||
|
"& iframe": {
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
transform:
|
||||||
|
settings.cfg.startpageType === "centered"
|
||||||
|
? ""
|
||||||
|
: settings.cfg.startpageType === "expanded"
|
||||||
|
? "scale(1.5)"
|
||||||
|
: "scale(2.4)",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : null
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper
|
||||||
|
className="settings-preview-draghandle"
|
||||||
|
sx={{
|
||||||
|
borderRadius: 0,
|
||||||
|
// height: "100%",
|
||||||
|
minHeight: "100vh",
|
||||||
|
width: "100%",
|
||||||
|
background:
|
||||||
|
settings.cfg.startpageType === "expanded"
|
||||||
|
? settings.cfg.startpage.position === "left"
|
||||||
|
? "linear-gradient(90deg,#272626,transparent)"
|
||||||
|
: settings.cfg.startpage.position === "center"
|
||||||
|
? "linear-gradient(180deg,transparent,#272626)"
|
||||||
|
: "linear-gradient(270deg,#272626,transparent)"
|
||||||
|
: theme.palette.background.default,
|
||||||
|
|
||||||
|
color: settings.cfg.startpageType === "expanded" ? "white" : "black",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<QuizPreviewLayoutByType
|
||||||
|
quizHeaderBlock={
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
margin:
|
||||||
|
settings.cfg.startpageType === "centered" ? "0 auto" : null,
|
||||||
|
padding: settings.cfg.startpageType === "standard" ? "" : "16px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
gap: "30px",
|
||||||
|
mb: "7px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={settings.cfg.startpage.logo || PenaLogo}
|
||||||
|
style={{
|
||||||
|
height: "40px",
|
||||||
|
maxWidth: "110px",
|
||||||
|
objectFit: "cover",
|
||||||
|
}}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontSize: "14px",
|
||||||
|
color:
|
||||||
|
settings.cfg.startpageType === "expanded"
|
||||||
|
? "white"
|
||||||
|
: theme.palette.text.primary,
|
||||||
|
wordBreak: "break-word",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{settings.cfg.info.orgname}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
quizMainBlock={
|
||||||
|
<>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "center",
|
||||||
|
flexGrow: settings.cfg.startpageType === "centered" ? 0 : 1,
|
||||||
|
alignItems:
|
||||||
|
settings.cfg.startpageType === "centered"
|
||||||
|
? "center"
|
||||||
|
: settings.cfg.startpageType === "expanded"
|
||||||
|
? settings.cfg.startpage.position === "center"
|
||||||
|
? "center"
|
||||||
|
: "start"
|
||||||
|
: "start",
|
||||||
|
marginTop: "28px",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: "26px",
|
||||||
|
fontStyle: "normal",
|
||||||
|
fontStretch: "normal",
|
||||||
|
lineHeight: "1.2",
|
||||||
|
overflowWrap: "break-word",
|
||||||
|
width: "100%",
|
||||||
|
textAlign:
|
||||||
|
settings.cfg.startpageType === "centered" ||
|
||||||
|
settings.cfg.startpage.position === "center"
|
||||||
|
? "center"
|
||||||
|
: "-moz-initial",
|
||||||
|
color:
|
||||||
|
settings.cfg.startpageType === "expanded"
|
||||||
|
? "white"
|
||||||
|
: theme.palette.text.primary,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{settings.name}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontSize: "16px",
|
||||||
|
margin: "16px 0 30px",
|
||||||
|
overflowWrap: "break-word",
|
||||||
|
width: "100%",
|
||||||
|
textAlign:
|
||||||
|
settings.cfg.startpageType === "centered" ||
|
||||||
|
settings.cfg.startpage.position === "center"
|
||||||
|
? "center"
|
||||||
|
: "-moz-initial",
|
||||||
|
color:
|
||||||
|
settings.cfg.startpageType === "expanded"
|
||||||
|
? "white"
|
||||||
|
: theme.palette.text.primary,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{settings.cfg.startpage.description}
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
width={
|
||||||
|
settings.cfg.startpageType === "standard" ? "100%" : "auto"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
sx={{
|
||||||
|
fontSize: "18px",
|
||||||
|
padding: "10px 30px",
|
||||||
|
width: "auto",
|
||||||
|
background: theme.palette.primary.main,
|
||||||
|
}}
|
||||||
|
onClick={() => setCurrentQuizStep("question")}
|
||||||
|
>
|
||||||
|
{settings.cfg.startpage.button.trim()
|
||||||
|
? settings.cfg.startpage.button
|
||||||
|
: "Пройти тест"}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
mt: "46px",
|
||||||
|
display: "flex",
|
||||||
|
flexGrow:
|
||||||
|
settings.cfg.startpageType === "centered"
|
||||||
|
? isMobile
|
||||||
|
? 0
|
||||||
|
: 1
|
||||||
|
: 0,
|
||||||
|
gap: "20px",
|
||||||
|
alignItems: "flex-end",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
width: "100%",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box sx={{ maxWidth: "300px" }}>
|
||||||
|
{settings.cfg.info.site && (
|
||||||
|
<Link mb="16px" href={settings.cfg.info.site}>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontSize: "16px",
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
overflow: "hidden",
|
||||||
|
textOverflow: "ellipsis",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
maxWidth: isTablet ? "200px" : "300px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{settings.cfg.info.site}
|
||||||
|
</Typography>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
{settings.cfg.info.clickable ? (
|
||||||
|
isMobileDevice ? (
|
||||||
|
<Link href={`tel:${settings.cfg.info.phonenumber}`}>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontSize: "16px",
|
||||||
|
color:
|
||||||
|
settings.cfg.startpageType === "expanded"
|
||||||
|
? "#FFFFFF"
|
||||||
|
: theme.palette.text.primary,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{settings.cfg.info.phonenumber}
|
||||||
|
</Typography>
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<ButtonBase onClick={handleCopyNumber}>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontSize: "16px",
|
||||||
|
color:
|
||||||
|
settings.cfg.startpageType === "expanded"
|
||||||
|
? "#FFFFFF"
|
||||||
|
: theme.palette.text.primary,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{settings.cfg.info.phonenumber}
|
||||||
|
</Typography>
|
||||||
|
</ButtonBase>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontSize: "16px",
|
||||||
|
marginTop: "5px",
|
||||||
|
color:
|
||||||
|
settings.cfg.startpageType === "expanded"
|
||||||
|
? "#FFFFFF"
|
||||||
|
: theme.palette.text.primary,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{settings.cfg.info.phonenumber}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
overflowWrap: "break-word",
|
||||||
|
fontSize: "12px",
|
||||||
|
maxHeight: "120px",
|
||||||
|
overflow: "auto",
|
||||||
|
marginTop: "5px",
|
||||||
|
"&::-webkit-scrollbar": { width: 0 },
|
||||||
|
color:
|
||||||
|
settings.cfg.startpageType === "expanded"
|
||||||
|
? "white"
|
||||||
|
: theme.palette.text.primary,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{settings.cfg.info.law}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{show_badge && (
|
||||||
|
<Box
|
||||||
|
component={Link}
|
||||||
|
target={"_blank"}
|
||||||
|
href={"https://quiz.pena.digital"}
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "15px",
|
||||||
|
textDecoration: "none",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<NameplateLogo
|
||||||
|
style={{
|
||||||
|
fontSize: "34px",
|
||||||
|
color:
|
||||||
|
settings.cfg.startpageType === "expanded"
|
||||||
|
? "#FFFFFF"
|
||||||
|
: quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "#151515"
|
||||||
|
: "#FFFFFF",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
color:
|
||||||
|
settings.cfg.startpageType === "expanded"
|
||||||
|
? "#F5F7FF"
|
||||||
|
: quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "#4D4D4D"
|
||||||
|
: "#F5F7FF",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Сделано на PenaQuiz
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
backgroundBlock={background}
|
||||||
|
startpageType={settings.cfg.startpageType}
|
||||||
|
alignType={settings.cfg.startpage.position}
|
||||||
|
/>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -11,88 +11,103 @@ import { Question } from "./Question";
|
|||||||
import { ResultForm } from "./ResultForm";
|
import { ResultForm } from "./ResultForm";
|
||||||
import { StartPageViewPublication } from "./StartPageViewPublication";
|
import { StartPageViewPublication } from "./StartPageViewPublication";
|
||||||
|
|
||||||
|
|
||||||
export default function ViewPublicationPage() {
|
export default function ViewPublicationPage() {
|
||||||
const { settings, recentlyCompleted } = useQuizData();
|
const { settings, recentlyCompleted } = useQuizData();
|
||||||
let currentQuizStep = useQuizViewStore(state => state.currentQuizStep);
|
let currentQuizStep = useQuizViewStore((state) => state.currentQuizStep);
|
||||||
const isMobileMini = useRootContainerSize() < 382;
|
const isMobileMini = useRootContainerSize() < 382;
|
||||||
const {
|
const {
|
||||||
currentQuestion,
|
currentQuestion,
|
||||||
currentQuestionStepNumber,
|
currentQuestionStepNumber,
|
||||||
isNextButtonEnabled,
|
isNextButtonEnabled,
|
||||||
isPreviousButtonEnabled,
|
isPreviousButtonEnabled,
|
||||||
moveToPrevQuestion,
|
moveToPrevQuestion,
|
||||||
moveToNextQuestion,
|
moveToNextQuestion,
|
||||||
showResultAfterContactForm,
|
showResultAfterContactForm,
|
||||||
} = useQuestionFlowControl();
|
} = useQuestionFlowControl();
|
||||||
|
|
||||||
useEffect(function setFaviconAndTitle() {
|
useEffect(
|
||||||
const link = document.querySelector('link[rel="icon"]');
|
function setFaviconAndTitle() {
|
||||||
if (link && settings.cfg.startpage.favIcon) {
|
const link = document.querySelector('link[rel="icon"]');
|
||||||
link.setAttribute("href", settings.cfg.startpage.favIcon);
|
if (link && settings.cfg.startpage.favIcon) {
|
||||||
}
|
link.setAttribute("href", settings.cfg.startpage.favIcon);
|
||||||
|
}
|
||||||
|
|
||||||
document.title = settings.name;
|
document.title = settings.name;
|
||||||
}, [settings]);
|
},
|
||||||
|
[settings]
|
||||||
|
);
|
||||||
|
|
||||||
if (recentlyCompleted) throw new Error("Quiz already completed");
|
if (recentlyCompleted) throw new Error("Quiz already completed");
|
||||||
if (currentQuizStep === "startpage" && settings.cfg.noStartPage) currentQuizStep = "question";
|
if (currentQuizStep === "startpage" && settings.cfg.noStartPage)
|
||||||
|
currentQuizStep = "question";
|
||||||
|
|
||||||
let quizStepElement: ReactElement;
|
let quizStepElement: ReactElement;
|
||||||
switch (currentQuizStep) {
|
switch (currentQuizStep) {
|
||||||
case "startpage": {
|
case "startpage": {
|
||||||
quizStepElement = <StartPageViewPublication />;
|
quizStepElement = <StartPageViewPublication />;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case "question": {
|
|
||||||
if (currentQuestion.type === "result") {
|
|
||||||
quizStepElement = <ResultForm resultQuestion={currentQuestion} />;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
quizStepElement = (
|
|
||||||
<Question
|
|
||||||
currentQuestion={currentQuestion}
|
|
||||||
currentQuestionStepNumber={currentQuestionStepNumber}
|
|
||||||
prevButton={
|
|
||||||
<Button
|
|
||||||
disabled={!isPreviousButtonEnabled}
|
|
||||||
variant="contained"
|
|
||||||
sx={{ fontSize: "16px", padding: "10px 15px" }}
|
|
||||||
onClick={moveToPrevQuestion}
|
|
||||||
>
|
|
||||||
{isMobileMini ? "←" : "← Назад"}
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
nextButton={
|
|
||||||
<Button
|
|
||||||
disabled={!isNextButtonEnabled}
|
|
||||||
variant="contained"
|
|
||||||
sx={{ fontSize: "16px", padding: "10px 15px" }}
|
|
||||||
onClick={moveToNextQuestion}
|
|
||||||
>
|
|
||||||
Далее →
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "contactform": {
|
|
||||||
quizStepElement = (
|
|
||||||
<ContactForm
|
|
||||||
currentQuestion={currentQuestion}
|
|
||||||
onShowResult={showResultAfterContactForm}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: notReachable(currentQuizStep);
|
|
||||||
}
|
}
|
||||||
|
case "question": {
|
||||||
|
if (currentQuestion.type === "result") {
|
||||||
|
quizStepElement = <ResultForm resultQuestion={currentQuestion} />;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
quizStepElement = (
|
||||||
<ThemeProvider theme={quizThemes[settings.cfg.theme || "StandardTheme"].theme}>
|
<Question
|
||||||
{quizStepElement}
|
currentQuestion={currentQuestion}
|
||||||
</ThemeProvider>
|
currentQuestionStepNumber={currentQuestionStepNumber}
|
||||||
);
|
prevButton={
|
||||||
}
|
<Button
|
||||||
|
disabled={!isPreviousButtonEnabled}
|
||||||
|
variant="contained"
|
||||||
|
sx={{
|
||||||
|
fontSize: "16px",
|
||||||
|
padding: "10px 15px",
|
||||||
|
color: "#FFFFFF",
|
||||||
|
border: "1px solid #9A9AAF",
|
||||||
|
background: "rgba(154,154,175, 0.2)",
|
||||||
|
"&:disabled": {
|
||||||
|
color: "#9A9AAF",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onClick={moveToPrevQuestion}
|
||||||
|
>
|
||||||
|
{isMobileMini ? "←" : "← Назад"}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
nextButton={
|
||||||
|
<Button
|
||||||
|
disabled={!isNextButtonEnabled}
|
||||||
|
variant="contained"
|
||||||
|
sx={{ fontSize: "16px", padding: "10px 15px" }}
|
||||||
|
onClick={moveToNextQuestion}
|
||||||
|
>
|
||||||
|
Далее →
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "contactform": {
|
||||||
|
quizStepElement = (
|
||||||
|
<ContactForm
|
||||||
|
currentQuestion={currentQuestion}
|
||||||
|
onShowResult={showResultAfterContactForm}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
notReachable(currentQuizStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeProvider
|
||||||
|
theme={quizThemes[settings.cfg.theme || "StandardTheme"].theme}
|
||||||
|
>
|
||||||
|
{quizStepElement}
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@ -14,97 +14,101 @@ import { useQuizData } from "@contexts/QuizDataContext";
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
type DateProps = {
|
type DateProps = {
|
||||||
currentQuestion: QuizQuestionDate;
|
currentQuestion: QuizQuestionDate;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Date = ({ currentQuestion }: DateProps) => {
|
export const Date = ({ currentQuestion }: DateProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { settings, quizId } = useQuizData();
|
const { settings, quizId } = useQuizData();
|
||||||
const { answers } = useQuizViewStore();
|
const { answers } = useQuizViewStore();
|
||||||
const answer = answers.find(
|
const answer = answers.find(
|
||||||
({ questionId }) => questionId === currentQuestion.id
|
({ questionId }) => questionId === currentQuestion.id
|
||||||
)?.answer as string;
|
)?.answer as string;
|
||||||
const currentAnswer = moment(answer) || moment();
|
const currentAnswer = moment(answer) || moment();
|
||||||
const [isSending, setIsSending] = useState<boolean>(false);
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
|
<Typography
|
||||||
{currentQuestion.title}
|
variant="h5"
|
||||||
</Typography>
|
color={theme.palette.text.primary}
|
||||||
<Box
|
sx={{ wordBreak: "break-word" }}
|
||||||
|
>
|
||||||
|
{currentQuestion.title}
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
marginTop: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DatePicker
|
||||||
|
slots={{
|
||||||
|
openPickerIcon: () => (
|
||||||
|
<CalendarIcon
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
"& path": { stroke: theme.palette.primary.main },
|
||||||
flexDirection: "column",
|
"& rect": { stroke: theme.palette.primary.main },
|
||||||
width: "100%",
|
|
||||||
marginTop: "20px",
|
|
||||||
}}
|
}}
|
||||||
>
|
/>
|
||||||
<DatePicker
|
),
|
||||||
slots={{
|
}}
|
||||||
openPickerIcon: () => (
|
value={currentAnswer}
|
||||||
<CalendarIcon
|
onChange={async (date) => {
|
||||||
sx={{
|
if (isSending || !date) return;
|
||||||
"& path": { stroke: theme.palette.primary.main },
|
|
||||||
"& rect": { stroke: theme.palette.primary.main },
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
value={currentAnswer}
|
|
||||||
onChange={async (date) => {
|
|
||||||
if (isSending || !date) return;
|
|
||||||
|
|
||||||
setIsSending(true);
|
setIsSending(true);
|
||||||
try {
|
try {
|
||||||
await sendAnswer({
|
await sendAnswer({
|
||||||
questionId: currentQuestion.id,
|
questionId: currentQuestion.id,
|
||||||
body: moment(date).format("YYYY.MM.DD"),
|
body: moment(date).format("YYYY.MM.DD"),
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
});
|
});
|
||||||
|
|
||||||
updateAnswer(
|
updateAnswer(currentQuestion.id, date, 0);
|
||||||
currentQuestion.id,
|
} catch (e) {
|
||||||
date,
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
0
|
}
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsSending(false);
|
setIsSending(false);
|
||||||
}}
|
}}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
openPickerButton: {
|
openPickerButton: {
|
||||||
sx: {
|
sx: {
|
||||||
p: 0,
|
p: 0,
|
||||||
},
|
},
|
||||||
"data-cy": "open-datepicker",
|
"data-cy": "open-datepicker",
|
||||||
},
|
},
|
||||||
layout: {
|
layout: {
|
||||||
sx: { backgroundColor: theme.palette.background.default },
|
sx: { backgroundColor: theme.palette.background.default },
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
"& .MuiInputBase-root": {
|
"& .MuiInputBase-root": {
|
||||||
backgroundColor: quizThemes[settings.cfg.theme].isLight
|
backgroundColor: settings.cfg.design
|
||||||
? "white"
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
: theme.palette.background.default,
|
? "#F2F3F7"
|
||||||
borderRadius: "10px",
|
: "rgba(154,154,175, 0.2)"
|
||||||
maxWidth: "250px",
|
: quizThemes[settings.cfg.theme].isLight
|
||||||
pr: "22px",
|
? "white"
|
||||||
"& input": {
|
: theme.palette.background.default,
|
||||||
py: "11px",
|
borderRadius: "10px",
|
||||||
pl: "20px",
|
maxWidth: "250px",
|
||||||
lineHeight: "19px",
|
pr: "22px",
|
||||||
},
|
"& input": {
|
||||||
"& fieldset": {
|
py: "11px",
|
||||||
borderColor: "#9A9AAF",
|
pl: "20px",
|
||||||
},
|
lineHeight: "19px",
|
||||||
},
|
},
|
||||||
}}
|
"& fieldset": {
|
||||||
/>
|
borderColor: "#9A9AAF",
|
||||||
</Box>
|
},
|
||||||
</Box>
|
},
|
||||||
);
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
FormControl,
|
FormControl,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
Radio,
|
Radio,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
Typography,
|
Typography,
|
||||||
useTheme
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
|
||||||
import { deleteAnswer, updateAnswer, useQuizViewStore } from "@stores/quizView";
|
import { deleteAnswer, updateAnswer, useQuizViewStore } from "@stores/quizView";
|
||||||
@ -19,169 +19,189 @@ import { enqueueSnackbar } from "notistack";
|
|||||||
import type { QuizQuestionEmoji } from "../../../model/questionTypes/emoji";
|
import type { QuizQuestionEmoji } from "../../../model/questionTypes/emoji";
|
||||||
import { useQuizData } from "@contexts/QuizDataContext";
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
import { polyfillCountryFlagEmojis } from "country-flag-emoji-polyfill";
|
import { polyfillCountryFlagEmojis } from "country-flag-emoji-polyfill";
|
||||||
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
|
|
||||||
polyfillCountryFlagEmojis();
|
polyfillCountryFlagEmojis();
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
type EmojiProps = {
|
type EmojiProps = {
|
||||||
currentQuestion: QuizQuestionEmoji;
|
currentQuestion: QuizQuestionEmoji;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Emoji = ({ currentQuestion }: EmojiProps) => {
|
export const Emoji = ({ currentQuestion }: EmojiProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { quizId } = useQuizData();
|
const { quizId, settings } = useQuizData();
|
||||||
const { answers } = useQuizViewStore();
|
const { answers } = useQuizViewStore();
|
||||||
const { answer } =
|
const { answer } =
|
||||||
answers.find(
|
answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
|
||||||
({ questionId }) => questionId === currentQuestion.id
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
) ?? {};
|
|
||||||
const [isSending, setIsSending] = useState<boolean>(false);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography
|
<Typography
|
||||||
variant="h5"
|
variant="h5"
|
||||||
color={theme.palette.text.primary}
|
color={theme.palette.text.primary}
|
||||||
sx={{ wordBreak: "break-word" }}
|
sx={{ wordBreak: "break-word" }}
|
||||||
>{currentQuestion.title}</Typography>
|
>
|
||||||
<RadioGroup
|
{currentQuestion.title}
|
||||||
name={currentQuestion.id}
|
</Typography>
|
||||||
value={currentQuestion.content.variants.findIndex(
|
<RadioGroup
|
||||||
({ id }) => answer === id
|
name={currentQuestion.id}
|
||||||
)}
|
value={currentQuestion.content.variants.findIndex(
|
||||||
onChange={({ target }) => {
|
({ id }) => answer === id
|
||||||
updateAnswer(
|
)}
|
||||||
currentQuestion.id,
|
onChange={({ target }) => {
|
||||||
currentQuestion.content.variants[Number(target.value)].answer,
|
updateAnswer(
|
||||||
currentQuestion.content.variants[Number(target.value)].points || 0
|
currentQuestion.id,
|
||||||
);
|
currentQuestion.content.variants[Number(target.value)].answer,
|
||||||
}
|
currentQuestion.content.variants[Number(target.value)].points || 0
|
||||||
}
|
);
|
||||||
sx={{
|
}}
|
||||||
display: "flex",
|
sx={{
|
||||||
flexWrap: "wrap",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexWrap: "wrap",
|
||||||
justifyContent: "space-between",
|
flexDirection: "row",
|
||||||
marginTop: "20px",
|
justifyContent: "space-between",
|
||||||
}}
|
marginTop: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{ display: "flex", width: "100%", gap: "42px", flexWrap: "wrap" }}
|
||||||
|
>
|
||||||
|
{currentQuestion.content.variants.map((variant, index) => (
|
||||||
|
<FormControl
|
||||||
|
key={variant.id}
|
||||||
|
disabled={isSending}
|
||||||
|
sx={{
|
||||||
|
borderRadius: "12px",
|
||||||
|
border: `1px solid`,
|
||||||
|
borderColor:
|
||||||
|
answer === variant.id
|
||||||
|
? theme.palette.primary.main
|
||||||
|
: "#9A9AAF",
|
||||||
|
overflow: "hidden",
|
||||||
|
maxWidth: "317px",
|
||||||
|
width: "100%",
|
||||||
|
height: "255px",
|
||||||
|
background: settings.cfg.design
|
||||||
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "#F2F3F7"
|
||||||
|
: "rgba(154,154,175, 0.2)"
|
||||||
|
: "transparent",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: "flex", width: "100%", gap: "42px", flexWrap: "wrap" }}>
|
<Box
|
||||||
{currentQuestion.content.variants.map((variant, index) => (
|
sx={{
|
||||||
<FormControl
|
display: "flex",
|
||||||
key={variant.id}
|
alignItems: "center",
|
||||||
disabled={isSending}
|
height: "193px",
|
||||||
sx={{
|
background: "#ffffff",
|
||||||
borderRadius: "12px",
|
}}
|
||||||
border: `1px solid`,
|
>
|
||||||
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
|
<Box
|
||||||
overflow: "hidden",
|
sx={{
|
||||||
maxWidth: "317px",
|
width: "100%",
|
||||||
width: "100%",
|
display: "flex",
|
||||||
height: "255px",
|
justifyContent: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
{variant.extendedText && (
|
||||||
sx={{
|
<Typography fontSize={"100px"}>
|
||||||
display: "flex",
|
{variant.extendedText}
|
||||||
alignItems: "center",
|
</Typography>
|
||||||
height: "193px",
|
)}
|
||||||
background: "#ffffff",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{variant.extendedText && (
|
|
||||||
<Typography fontSize={"100px"}>
|
|
||||||
{variant.extendedText}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<FormControlLabel
|
|
||||||
key={variant.id}
|
|
||||||
sx={{
|
|
||||||
margin: 0,
|
|
||||||
padding: "15px",
|
|
||||||
color: theme.palette.text.primary,
|
|
||||||
display: "flex",
|
|
||||||
gap: "10px",
|
|
||||||
alignItems:
|
|
||||||
variant.answer.length <= 60 ? "center" : "flex-start",
|
|
||||||
position: "relative",
|
|
||||||
height: "80px",
|
|
||||||
"& .MuiFormControlLabel-label": {
|
|
||||||
wordBreak: "break-word",
|
|
||||||
height: variant.answer.length <= 60 ? undefined : "60px",
|
|
||||||
overflow: "auto",
|
|
||||||
paddingLeft: "45px",
|
|
||||||
"&::-webkit-scrollbar": {
|
|
||||||
width: "4px",
|
|
||||||
},
|
|
||||||
"&::-webkit-scrollbar-thumb": {
|
|
||||||
backgroundColor: "#b8babf",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
value={index}
|
|
||||||
onClick={async (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
if (isSending) return;
|
|
||||||
|
|
||||||
setIsSending(true);
|
|
||||||
try {
|
|
||||||
await sendAnswer({
|
|
||||||
questionId: currentQuestion.id,
|
|
||||||
body: currentQuestion.content.variants[index].extendedText + " " + currentQuestion.content.variants[index].answer,
|
|
||||||
qid: quizId,
|
|
||||||
});
|
|
||||||
|
|
||||||
updateAnswer(
|
|
||||||
currentQuestion.id,
|
|
||||||
currentQuestion.content.variants[index].id,
|
|
||||||
currentQuestion.content.variants[index].points || 0
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (answer === currentQuestion.content.variants[index].id) {
|
|
||||||
deleteAnswer(currentQuestion.id);
|
|
||||||
try {
|
|
||||||
await sendAnswer({
|
|
||||||
questionId: currentQuestion.id,
|
|
||||||
body: "",
|
|
||||||
qid: quizId,
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsSending(false);
|
|
||||||
}}
|
|
||||||
|
|
||||||
control={
|
|
||||||
<Radio checkedIcon={<RadioCheck color={theme.palette.primary.main} />} icon={<RadioIcon />} />
|
|
||||||
}
|
|
||||||
label={
|
|
||||||
<Box sx={{ display: "flex", gap: "10px" }}>
|
|
||||||
<Typography sx={{
|
|
||||||
wordBreak: "break-word",
|
|
||||||
lineHeight: "normal",
|
|
||||||
}}>{variant.answer}</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
))}
|
|
||||||
</Box>
|
</Box>
|
||||||
</RadioGroup>
|
</Box>
|
||||||
|
<FormControlLabel
|
||||||
|
key={variant.id}
|
||||||
|
sx={{
|
||||||
|
margin: 0,
|
||||||
|
padding: "15px",
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
display: "flex",
|
||||||
|
gap: "10px",
|
||||||
|
alignItems:
|
||||||
|
variant.answer.length <= 60 ? "center" : "flex-start",
|
||||||
|
position: "relative",
|
||||||
|
height: "80px",
|
||||||
|
"& .MuiFormControlLabel-label": {
|
||||||
|
wordBreak: "break-word",
|
||||||
|
height: variant.answer.length <= 60 ? undefined : "60px",
|
||||||
|
overflow: "auto",
|
||||||
|
paddingLeft: "45px",
|
||||||
|
"&::-webkit-scrollbar": {
|
||||||
|
width: "4px",
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb": {
|
||||||
|
backgroundColor: "#b8babf",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
value={index}
|
||||||
|
onClick={async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
if (isSending) return;
|
||||||
|
|
||||||
|
setIsSending(true);
|
||||||
|
try {
|
||||||
|
await sendAnswer({
|
||||||
|
questionId: currentQuestion.id,
|
||||||
|
body:
|
||||||
|
currentQuestion.content.variants[index].extendedText +
|
||||||
|
" " +
|
||||||
|
currentQuestion.content.variants[index].answer,
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
|
||||||
|
updateAnswer(
|
||||||
|
currentQuestion.id,
|
||||||
|
currentQuestion.content.variants[index].id,
|
||||||
|
currentQuestion.content.variants[index].points || 0
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (answer === currentQuestion.content.variants[index].id) {
|
||||||
|
deleteAnswer(currentQuestion.id);
|
||||||
|
try {
|
||||||
|
await sendAnswer({
|
||||||
|
questionId: currentQuestion.id,
|
||||||
|
body: "",
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsSending(false);
|
||||||
|
}}
|
||||||
|
control={
|
||||||
|
<Radio
|
||||||
|
checkedIcon={
|
||||||
|
<RadioCheck color={theme.palette.primary.main} />
|
||||||
|
}
|
||||||
|
icon={<RadioIcon />}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={
|
||||||
|
<Box sx={{ display: "flex", gap: "10px" }}>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
wordBreak: "break-word",
|
||||||
|
lineHeight: "normal",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{variant.answer}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
</RadioGroup>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -189,7 +189,7 @@ export const File = ({ currentQuestion }: FileProps) => {
|
|||||||
justifyContent: "flex-start",
|
justifyContent: "flex-start",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
padding: "33px 44px 33px 55px",
|
padding: "33px 44px 33px 55px",
|
||||||
backgroundColor: theme.palette.background.default,
|
backgroundColor: "#F2F3F7",
|
||||||
border: `1px solid ${isDropzoneHighlighted ? "red" : "#9A9AAF"}`,
|
border: `1px solid ${isDropzoneHighlighted ? "red" : "#9A9AAF"}`,
|
||||||
borderRadius: "8px",
|
borderRadius: "8px",
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
Radio,
|
Radio,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
Typography,
|
Typography,
|
||||||
useTheme
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
|
||||||
import { deleteAnswer, updateAnswer, useQuizViewStore } from "@stores/quizView";
|
import { deleteAnswer, updateAnswer, useQuizViewStore } from "@stores/quizView";
|
||||||
@ -17,149 +17,172 @@ import { useRootContainerSize } from "../../../contexts/RootContainerWidthContex
|
|||||||
import type { QuizQuestionImages } from "../../../model/questionTypes/images";
|
import type { QuizQuestionImages } from "../../../model/questionTypes/images";
|
||||||
import { useQuizData } from "@contexts/QuizDataContext";
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
|
|
||||||
type ImagesProps = {
|
type ImagesProps = {
|
||||||
currentQuestion: QuizQuestionImages;
|
currentQuestion: QuizQuestionImages;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Images = ({ currentQuestion }: ImagesProps) => {
|
export const Images = ({ currentQuestion }: ImagesProps) => {
|
||||||
const { quizId } = useQuizData();
|
const { quizId } = useQuizData();
|
||||||
const { answers } = useQuizViewStore();
|
const { answers } = useQuizViewStore();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer;
|
const answer = answers.find(
|
||||||
const [isSending, setIsSending] = useState<boolean>(false);
|
({ questionId }) => questionId === currentQuestion.id
|
||||||
const isTablet = useRootContainerSize() < 1000;
|
)?.answer;
|
||||||
const isMobile = useRootContainerSize() < 500;
|
const { settings } = useQuizData();
|
||||||
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
|
const isTablet = useRootContainerSize() < 1000;
|
||||||
|
const isMobile = useRootContainerSize() < 500;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>{currentQuestion.title}</Typography>
|
<Typography
|
||||||
<RadioGroup
|
variant="h5"
|
||||||
name={currentQuestion.id}
|
color={theme.palette.text.primary}
|
||||||
value={currentQuestion.content.variants.findIndex(
|
sx={{ wordBreak: "break-word" }}
|
||||||
({ id }) => answer === id
|
>
|
||||||
)}
|
{currentQuestion.title}
|
||||||
sx={{
|
</Typography>
|
||||||
display: "flex",
|
<RadioGroup
|
||||||
flexWrap: "wrap",
|
name={currentQuestion.id}
|
||||||
flexDirection: "row",
|
value={currentQuestion.content.variants.findIndex(
|
||||||
justifyContent: "space-between",
|
({ id }) => answer === id
|
||||||
marginTop: "20px",
|
)}
|
||||||
}}
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginTop: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "grid",
|
||||||
|
gap: "15px",
|
||||||
|
gridTemplateColumns: isTablet
|
||||||
|
? isMobile
|
||||||
|
? "repeat(1, 1fr)"
|
||||||
|
: "repeat(2, 1fr)"
|
||||||
|
: "repeat(3, 1fr)",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{currentQuestion.content.variants.map((variant, index) => (
|
||||||
|
<Box
|
||||||
|
key={index}
|
||||||
|
sx={{
|
||||||
|
cursor: "pointer",
|
||||||
|
borderRadius: "5px",
|
||||||
|
border: `1px solid`,
|
||||||
|
borderColor:
|
||||||
|
answer === variant.id
|
||||||
|
? theme.palette.primary.main
|
||||||
|
: "#9A9AAF",
|
||||||
|
background: settings.cfg.design
|
||||||
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "#FFFFFF"
|
||||||
|
: "rgba(154,154,175, 0.2)"
|
||||||
|
: "transparent",
|
||||||
|
transition: "opacity 0.5s ease",
|
||||||
|
opacity: isSending ? 0.5 : 1,
|
||||||
|
pointerEvents: isSending ? "none" : "auto",
|
||||||
|
}}
|
||||||
|
onClick={async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
if (isSending) return;
|
||||||
|
|
||||||
|
setIsSending(true);
|
||||||
|
try {
|
||||||
|
await sendAnswer({
|
||||||
|
questionId: currentQuestion.id,
|
||||||
|
body: `${currentQuestion.content.variants[index].answer} <img style="width:100%; max-width:250px; max-height:250px" src="${currentQuestion.content.variants[index].extendedText}"/>`,
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
updateAnswer(
|
||||||
|
currentQuestion.id,
|
||||||
|
currentQuestion.content.variants[index].id,
|
||||||
|
currentQuestion.content.variants[index].points || 0
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (answer === currentQuestion.content.variants[index].id) {
|
||||||
|
deleteAnswer(currentQuestion.id);
|
||||||
|
try {
|
||||||
|
await sendAnswer({
|
||||||
|
questionId: currentQuestion.id,
|
||||||
|
body: "",
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsSending(false);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
||||||
sx={{
|
<Box sx={{ width: "100%", height: "300px" }}>
|
||||||
display: "grid",
|
{variant.extendedText && (
|
||||||
gap: "15px",
|
<img
|
||||||
gridTemplateColumns: isTablet
|
src={variant.extendedText}
|
||||||
? isMobile
|
alt=""
|
||||||
? "repeat(1, 1fr)"
|
style={{
|
||||||
: "repeat(2, 1fr)"
|
display: "block",
|
||||||
: "repeat(3, 1fr)",
|
|
||||||
width: "100%",
|
width: "100%",
|
||||||
}}
|
height: "100%",
|
||||||
>
|
objectFit: "cover",
|
||||||
{currentQuestion.content.variants.map((variant, index) => (
|
}}
|
||||||
<Box
|
/>
|
||||||
key={index}
|
)}
|
||||||
sx={{
|
|
||||||
cursor: "pointer",
|
|
||||||
borderRadius: "5px",
|
|
||||||
border: `1px solid`,
|
|
||||||
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
|
|
||||||
transition: "opacity 0.5s ease",
|
|
||||||
opacity: isSending ? 0.5 : 1,
|
|
||||||
pointerEvents: isSending ? "none" : "auto",
|
|
||||||
}}
|
|
||||||
onClick={async (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
if (isSending) return;
|
|
||||||
|
|
||||||
setIsSending(true);
|
|
||||||
try {
|
|
||||||
await sendAnswer({
|
|
||||||
questionId: currentQuestion.id,
|
|
||||||
body: `${currentQuestion.content.variants[index].answer} <img style="width:100%; max-width:250px; max-height:250px" src="${currentQuestion.content.variants[index].extendedText}"/>`,
|
|
||||||
qid: quizId,
|
|
||||||
});
|
|
||||||
updateAnswer(
|
|
||||||
currentQuestion.id,
|
|
||||||
currentQuestion.content.variants[index].id,
|
|
||||||
currentQuestion.content.variants[index].points || 0
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (answer === currentQuestion.content.variants[index].id) {
|
|
||||||
deleteAnswer(currentQuestion.id);
|
|
||||||
try {
|
|
||||||
await sendAnswer({
|
|
||||||
questionId: currentQuestion.id,
|
|
||||||
body: "",
|
|
||||||
qid: quizId,
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsSending(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
|
||||||
<Box sx={{ width: "100%", height: "300px" }}>
|
|
||||||
{variant.extendedText && (
|
|
||||||
<img
|
|
||||||
src={variant.extendedText}
|
|
||||||
alt=""
|
|
||||||
style={{
|
|
||||||
display: "block",
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
objectFit: "cover",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<FormControlLabel
|
|
||||||
key={variant.id}
|
|
||||||
sx={{
|
|
||||||
textAlign: "center",
|
|
||||||
color: theme.palette.text.primary,
|
|
||||||
marginTop: "10px",
|
|
||||||
marginLeft: 0,
|
|
||||||
padding: "10px",
|
|
||||||
display: "flex",
|
|
||||||
alignItems:
|
|
||||||
variant.answer.length <= 60 ? "center" : "flex-start",
|
|
||||||
position: "relative",
|
|
||||||
height: "80px",
|
|
||||||
"& .MuiFormControlLabel-label": {
|
|
||||||
wordBreak: "break-word",
|
|
||||||
height: variant.answer.length <= 60 ? undefined : "60px",
|
|
||||||
overflow: "auto",
|
|
||||||
lineHeight: "normal",
|
|
||||||
paddingLeft: "45px",
|
|
||||||
"&::-webkit-scrollbar": {
|
|
||||||
width: "4px",
|
|
||||||
},
|
|
||||||
"&::-webkit-scrollbar-thumb": {
|
|
||||||
backgroundColor: "#b8babf",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
value={index}
|
|
||||||
control={
|
|
||||||
<Radio checkedIcon={<RadioCheck color={theme.palette.primary.main} />} icon={<RadioIcon />} />
|
|
||||||
}
|
|
||||||
label={variant.answer}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
))}
|
|
||||||
</Box>
|
</Box>
|
||||||
</RadioGroup>
|
</Box>
|
||||||
|
<FormControlLabel
|
||||||
|
key={variant.id}
|
||||||
|
sx={{
|
||||||
|
textAlign: "center",
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
marginTop: "10px",
|
||||||
|
marginLeft: 0,
|
||||||
|
padding: "10px",
|
||||||
|
display: "flex",
|
||||||
|
alignItems:
|
||||||
|
variant.answer.length <= 60 ? "center" : "flex-start",
|
||||||
|
position: "relative",
|
||||||
|
height: "80px",
|
||||||
|
"& .MuiFormControlLabel-label": {
|
||||||
|
wordBreak: "break-word",
|
||||||
|
height: variant.answer.length <= 60 ? undefined : "60px",
|
||||||
|
overflow: "auto",
|
||||||
|
lineHeight: "normal",
|
||||||
|
paddingLeft: "45px",
|
||||||
|
"&::-webkit-scrollbar": {
|
||||||
|
width: "4px",
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb": {
|
||||||
|
backgroundColor: "#b8babf",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
value={index}
|
||||||
|
control={
|
||||||
|
<Radio
|
||||||
|
checkedIcon={
|
||||||
|
<RadioCheck color={theme.palette.primary.main} />
|
||||||
|
}
|
||||||
|
icon={<RadioIcon />}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={variant.answer}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
</RadioGroup>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -18,445 +18,454 @@ import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
|
|||||||
import type { ChangeEvent, SyntheticEvent } from "react";
|
import type { ChangeEvent, SyntheticEvent } from "react";
|
||||||
|
|
||||||
type NumberProps = {
|
type NumberProps = {
|
||||||
currentQuestion: QuizQuestionNumber;
|
currentQuestion: QuizQuestionNumber;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Number = ({ currentQuestion }: NumberProps) => {
|
export const Number = ({ currentQuestion }: NumberProps) => {
|
||||||
const { settings, quizId } = useQuizData();
|
const { settings, quizId } = useQuizData();
|
||||||
const [inputValue, setInputValue] = useState<string>("0");
|
const [inputValue, setInputValue] = useState<string>("0");
|
||||||
const [minRange, setMinRange] = useState<string>("0");
|
const [minRange, setMinRange] = useState<string>("0");
|
||||||
const [maxRange, setMaxRange] = useState<string>("100000000000");
|
const [maxRange, setMaxRange] = useState<string>("100000000000");
|
||||||
const [reversedInputValue, setReversedInputValue] = useState<string>("0");
|
const [reversedInputValue, setReversedInputValue] = useState<string>("0");
|
||||||
const [reversedMinRange, setReversedMinRange] = useState<string>("0");
|
const [reversedMinRange, setReversedMinRange] = useState<string>("0");
|
||||||
const [reversedMaxRange, setReversedMaxRange] =
|
const [reversedMaxRange, setReversedMaxRange] =
|
||||||
useState<string>("100000000000");
|
useState<string>("100000000000");
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { answers } = useQuizViewStore();
|
const { answers } = useQuizViewStore();
|
||||||
const [isSending, setIsSending] = useState<boolean>(false);
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
|
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
const [minBorder, maxBorder] = currentQuestion.content.range
|
const [minBorder, maxBorder] = currentQuestion.content.range
|
||||||
.split("—")
|
.split("—")
|
||||||
.map(window.Number);
|
.map(window.Number);
|
||||||
const min = minBorder < maxBorder ? minBorder : maxBorder;
|
const min = minBorder < maxBorder ? minBorder : maxBorder;
|
||||||
const max = minBorder < maxBorder ? maxBorder : minBorder;
|
const max = minBorder < maxBorder ? maxBorder : minBorder;
|
||||||
const reversed = minBorder > maxBorder;
|
const reversed = minBorder > maxBorder;
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
console.log("reversed:", reversed)
|
|
||||||
}, [reversed])
|
|
||||||
|
|
||||||
const sendAnswerToBackend = async (value: string, noUpdate = false) => {
|
useEffect(() => {
|
||||||
setIsSending(true);
|
console.log("reversed:", reversed);
|
||||||
try {
|
}, [reversed]);
|
||||||
await sendAnswer({
|
|
||||||
questionId: currentQuestion.id,
|
|
||||||
body: value,
|
|
||||||
qid: quizId,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!noUpdate) {
|
const sendAnswerToBackend = async (value: string, noUpdate = false) => {
|
||||||
updateAnswer(currentQuestion.id, value, 0);
|
setIsSending(true);
|
||||||
}
|
try {
|
||||||
} catch (e) {
|
await sendAnswer({
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
questionId: currentQuestion.id,
|
||||||
}
|
body: value,
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
|
||||||
setIsSending(false);
|
if (!noUpdate) {
|
||||||
};
|
updateAnswer(currentQuestion.id, value, 0);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
|
}
|
||||||
|
|
||||||
const updateValueDebounced = useDebouncedCallback(async (value: string) => {
|
setIsSending(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateValueDebounced = useDebouncedCallback(async (value: string) => {
|
||||||
|
if (reversed) {
|
||||||
|
const newValue =
|
||||||
|
window.Number(value) < window.Number(min)
|
||||||
|
? String(min)
|
||||||
|
: window.Number(value) > window.Number(max)
|
||||||
|
? String(max)
|
||||||
|
: value;
|
||||||
|
|
||||||
|
setReversedInputValue(newValue);
|
||||||
|
updateAnswer(
|
||||||
|
currentQuestion.id,
|
||||||
|
String(max + min - window.Number(newValue)),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
await sendAnswerToBackend(String(window.Number(newValue)), true);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newValue =
|
||||||
|
window.Number(value) < window.Number(minRange)
|
||||||
|
? minRange
|
||||||
|
: window.Number(value) > window.Number(maxRange)
|
||||||
|
? maxRange
|
||||||
|
: value;
|
||||||
|
|
||||||
|
setInputValue(newValue);
|
||||||
|
await sendAnswerToBackend(newValue);
|
||||||
|
}, 1000);
|
||||||
|
const updateMinRangeDebounced = useDebouncedCallback(
|
||||||
|
async (value: string, crowded = false) => {
|
||||||
|
if (reversed) {
|
||||||
|
const newMinRange = crowded
|
||||||
|
? window.Number(value.split("—")[1])
|
||||||
|
: max + min - window.Number(value.split("—")[0]) < min
|
||||||
|
? min
|
||||||
|
: max + min - window.Number(value.split("—")[0]);
|
||||||
|
|
||||||
|
const newMinValue =
|
||||||
|
window.Number(value.split("—")[0]) > max
|
||||||
|
? String(max)
|
||||||
|
: value.split("—")[0];
|
||||||
|
|
||||||
|
setReversedMinRange(
|
||||||
|
crowded ? String(max + min - window.Number(newMinValue)) : newMinValue
|
||||||
|
);
|
||||||
|
updateAnswer(
|
||||||
|
currentQuestion.id,
|
||||||
|
`${newMinRange}—${value.split("—")[1]}`,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
await sendAnswerToBackend(
|
||||||
|
`${newMinValue}—${value.split("—")[1]}`,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newMinValue = crowded
|
||||||
|
? maxRange
|
||||||
|
: window.Number(value.split("—")[0]) < min
|
||||||
|
? String(min)
|
||||||
|
: value.split("—")[0];
|
||||||
|
|
||||||
|
setMinRange(newMinValue);
|
||||||
|
await sendAnswerToBackend(`${newMinValue}—${value.split("—")[1]}`);
|
||||||
|
},
|
||||||
|
1000
|
||||||
|
);
|
||||||
|
const updateMaxRangeDebounced = useDebouncedCallback(
|
||||||
|
async (value: string, crowded = false) => {
|
||||||
|
if (reversed) {
|
||||||
|
const newMaxRange = crowded
|
||||||
|
? window.Number(value.split("—")[1])
|
||||||
|
: max + min - window.Number(value.split("—")[1]) > max
|
||||||
|
? max
|
||||||
|
: max + min - window.Number(value.split("—")[1]);
|
||||||
|
|
||||||
|
const newMaxValue =
|
||||||
|
window.Number(value.split("—")[1]) < min
|
||||||
|
? String(min)
|
||||||
|
: value.split("—")[1];
|
||||||
|
|
||||||
|
setReversedMaxRange(
|
||||||
|
crowded ? String(max + min - window.Number(newMaxValue)) : newMaxValue
|
||||||
|
);
|
||||||
|
updateAnswer(
|
||||||
|
currentQuestion.id,
|
||||||
|
`${value.split("—")[0]}—${newMaxRange}`,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
await sendAnswerToBackend(
|
||||||
|
`${value.split("—")[0]}—${newMaxValue}`,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newMaxValue = crowded
|
||||||
|
? minRange
|
||||||
|
: window.Number(value.split("—")[1]) > max
|
||||||
|
? String(max)
|
||||||
|
: value.split("—")[1];
|
||||||
|
|
||||||
|
setMaxRange(newMaxValue);
|
||||||
|
await sendAnswerToBackend(`${value.split("—")[0]}—${newMaxValue}`);
|
||||||
|
},
|
||||||
|
1000
|
||||||
|
);
|
||||||
|
const answer = answers.find(
|
||||||
|
({ questionId }) => questionId === currentQuestion.id
|
||||||
|
)?.answer as string;
|
||||||
|
|
||||||
|
const sliderValue =
|
||||||
|
answer ||
|
||||||
|
(reversed
|
||||||
|
? max + min - currentQuestion.content.start + "—" + max
|
||||||
|
: currentQuestion.content.start + "—" + max);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (answer) {
|
||||||
|
if (answer.includes("—")) {
|
||||||
if (reversed) {
|
if (reversed) {
|
||||||
const newValue =
|
setReversedMinRange(
|
||||||
window.Number(value) < window.Number(min)
|
String(max + min - window.Number(answer.split("—")[0]))
|
||||||
? String(min)
|
);
|
||||||
: window.Number(value) > window.Number(max)
|
setReversedMaxRange(
|
||||||
? String(max)
|
String(max + min - window.Number(answer.split("—")[1]))
|
||||||
: value;
|
);
|
||||||
|
|
||||||
setReversedInputValue(newValue);
|
|
||||||
updateAnswer(
|
|
||||||
currentQuestion.id,
|
|
||||||
String(max + min - window.Number(newValue)),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
await sendAnswerToBackend(String(window.Number(newValue)), true);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newValue =
|
|
||||||
window.Number(value) < window.Number(minRange)
|
|
||||||
? minRange
|
|
||||||
: window.Number(value) > window.Number(maxRange)
|
|
||||||
? maxRange
|
|
||||||
: value;
|
|
||||||
|
|
||||||
setInputValue(newValue);
|
|
||||||
await sendAnswerToBackend(newValue);
|
|
||||||
}, 1000);
|
|
||||||
const updateMinRangeDebounced = useDebouncedCallback(
|
|
||||||
async (value: string, crowded = false) => {
|
|
||||||
if (reversed) {
|
|
||||||
const newMinRange = crowded
|
|
||||||
? window.Number(value.split("—")[1])
|
|
||||||
: max + min - window.Number(value.split("—")[0]) < min
|
|
||||||
? min
|
|
||||||
: max + min - window.Number(value.split("—")[0]);
|
|
||||||
|
|
||||||
const newMinValue =
|
|
||||||
window.Number(value.split("—")[0]) > max
|
|
||||||
? String(max)
|
|
||||||
: value.split("—")[0];
|
|
||||||
|
|
||||||
setReversedMinRange(
|
|
||||||
crowded ? String(max + min - window.Number(newMinValue)) : newMinValue
|
|
||||||
);
|
|
||||||
updateAnswer(
|
|
||||||
currentQuestion.id,
|
|
||||||
`${newMinRange}—${value.split("—")[1]}`,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
await sendAnswerToBackend(
|
|
||||||
`${newMinValue}—${value.split("—")[1]}`,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newMinValue = crowded
|
|
||||||
? maxRange
|
|
||||||
: window.Number(value.split("—")[0]) < min
|
|
||||||
? String(min)
|
|
||||||
: value.split("—")[0];
|
|
||||||
|
|
||||||
setMinRange(newMinValue);
|
|
||||||
await sendAnswerToBackend(`${newMinValue}—${value.split("—")[1]}`);
|
|
||||||
},
|
|
||||||
1000
|
|
||||||
);
|
|
||||||
const updateMaxRangeDebounced = useDebouncedCallback(
|
|
||||||
async (value: string, crowded = false) => {
|
|
||||||
if (reversed) {
|
|
||||||
const newMaxRange = crowded
|
|
||||||
? window.Number(value.split("—")[1])
|
|
||||||
: max + min - window.Number(value.split("—")[1]) > max
|
|
||||||
? max
|
|
||||||
: max + min - window.Number(value.split("—")[1]);
|
|
||||||
|
|
||||||
const newMaxValue =
|
|
||||||
window.Number(value.split("—")[1]) < min
|
|
||||||
? String(min)
|
|
||||||
: value.split("—")[1];
|
|
||||||
|
|
||||||
setReversedMaxRange(
|
|
||||||
crowded ? String(max + min - window.Number(newMaxValue)) : newMaxValue
|
|
||||||
);
|
|
||||||
updateAnswer(
|
|
||||||
currentQuestion.id,
|
|
||||||
`${value.split("—")[0]}—${newMaxRange}`,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
await sendAnswerToBackend(
|
|
||||||
`${value.split("—")[0]}—${newMaxValue}`,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newMaxValue = crowded
|
|
||||||
? minRange
|
|
||||||
: window.Number(value.split("—")[1]) > max
|
|
||||||
? String(max)
|
|
||||||
: value.split("—")[1];
|
|
||||||
|
|
||||||
setMaxRange(newMaxValue);
|
|
||||||
await sendAnswerToBackend(`${value.split("—")[0]}—${newMaxValue}`);
|
|
||||||
},
|
|
||||||
1000
|
|
||||||
);
|
|
||||||
const answer = answers.find(
|
|
||||||
({ questionId }) => questionId === currentQuestion.id
|
|
||||||
)?.answer as string;
|
|
||||||
|
|
||||||
const sliderValue =
|
|
||||||
answer ||
|
|
||||||
(reversed
|
|
||||||
? max + min - currentQuestion.content.start + "—" + max
|
|
||||||
: currentQuestion.content.start + "—" + max);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (answer) {
|
|
||||||
if (answer.includes("—")) {
|
|
||||||
if (reversed) {
|
|
||||||
setReversedMinRange(
|
|
||||||
String(max + min - window.Number(answer.split("—")[0]))
|
|
||||||
);
|
|
||||||
setReversedMaxRange(
|
|
||||||
String(max + min - window.Number(answer.split("—")[1]))
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
setMinRange(answer.split("—")[0]);
|
|
||||||
setMaxRange(answer.split("—")[1]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (reversed) {
|
|
||||||
setReversedInputValue(String(max + min - window.Number(answer)));
|
|
||||||
} else {
|
|
||||||
setInputValue(answer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!answer) {
|
|
||||||
setMinRange(String(currentQuestion.content.start));
|
|
||||||
setMaxRange(String(max));
|
|
||||||
|
|
||||||
if (currentQuestion.content.chooseRange) {
|
|
||||||
setReversedMinRange(String(currentQuestion.content.start));
|
|
||||||
setReversedMaxRange(String(min));
|
|
||||||
}
|
|
||||||
|
|
||||||
setReversedInputValue(String(currentQuestion.content.start));
|
|
||||||
setInputValue(String(currentQuestion.content.start));
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onSliderChange = (_: Event, value: number | number[]) => {
|
|
||||||
const range = Array.isArray(value)
|
|
||||||
? `${value[0]}—${value[1]}`
|
|
||||||
: String(value);
|
|
||||||
|
|
||||||
updateAnswer(currentQuestion.id, range, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onChangeCommitted = async (
|
|
||||||
_: Event | SyntheticEvent<Element, Event>,
|
|
||||||
value: number | number[]
|
|
||||||
) => {
|
|
||||||
if (currentQuestion.content.chooseRange && Array.isArray(value)) {
|
|
||||||
if (reversed) {
|
|
||||||
const newMinReversedValue = String(max + min - value[0]);
|
|
||||||
const newMaxReversedValue = String(max + min - value[1]);
|
|
||||||
|
|
||||||
setMinRange(String(value[0]));
|
|
||||||
setMaxRange(String(value[1]));
|
|
||||||
setReversedMinRange(newMinReversedValue);
|
|
||||||
setReversedMaxRange(newMaxReversedValue);
|
|
||||||
await sendAnswerToBackend(
|
|
||||||
`${newMinReversedValue}—${newMaxReversedValue}`,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setMinRange(String(value[0]));
|
|
||||||
setMaxRange(String(value[1]));
|
|
||||||
await sendAnswerToBackend(`${value[0]}—${value[1]}`);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reversed) {
|
|
||||||
setReversedInputValue(String(max + min - window.Number(value)));
|
|
||||||
} else {
|
} else {
|
||||||
setInputValue(String(value));
|
setMinRange(answer.split("—")[0]);
|
||||||
|
setMaxRange(answer.split("—")[1]);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
await sendAnswerToBackend(String(value));
|
|
||||||
};
|
|
||||||
|
|
||||||
const changeValueLabelFormat = (value: number) => {
|
|
||||||
if (!reversed) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const [minSliderBorder, maxSliderBorder] = sliderValue
|
|
||||||
.split("—")
|
|
||||||
.map(window.Number);
|
|
||||||
|
|
||||||
if (value === minSliderBorder) {
|
|
||||||
return max + min - minSliderBorder;
|
|
||||||
}
|
|
||||||
|
|
||||||
return max + min - maxSliderBorder;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onInputChange = ({ target }: ChangeEvent<HTMLInputElement>) => {
|
|
||||||
const value = target.value.replace(/\D/g, "");
|
|
||||||
|
|
||||||
if (reversed) {
|
if (reversed) {
|
||||||
setReversedInputValue(value);
|
setReversedInputValue(String(max + min - window.Number(answer)));
|
||||||
} else {
|
} else {
|
||||||
setInputValue(value);
|
setInputValue(answer);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateValueDebounced(value);
|
if (!answer) {
|
||||||
};
|
setMinRange(String(currentQuestion.content.start));
|
||||||
|
setMaxRange(String(max));
|
||||||
|
|
||||||
const onMinInputChange = ({ target }: ChangeEvent<HTMLInputElement>) => {
|
if (currentQuestion.content.chooseRange) {
|
||||||
const newValue = target.value.replace(/\D/g, "");
|
setReversedMinRange(String(currentQuestion.content.start));
|
||||||
|
setReversedMaxRange(String(min));
|
||||||
|
}
|
||||||
|
|
||||||
if (reversed) {
|
setReversedInputValue(String(currentQuestion.content.start));
|
||||||
setReversedMinRange(newValue);
|
setInputValue(String(currentQuestion.content.start));
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
if (window.Number(newValue) <= window.Number(reversedMaxRange)) {
|
const onSliderChange = (_: Event, value: number | number[]) => {
|
||||||
const value = max + min - window.Number(reversedMaxRange);
|
const range = Array.isArray(value)
|
||||||
updateMinRangeDebounced(`${value}—${value}`, true);
|
? `${value[0]}—${value[1]}`
|
||||||
|
: String(value);
|
||||||
|
|
||||||
return;
|
updateAnswer(currentQuestion.id, range, 0);
|
||||||
}
|
};
|
||||||
|
|
||||||
updateMinRangeDebounced(
|
const onChangeCommitted = async (
|
||||||
`${newValue}—${max + min - window.Number(reversedMaxRange)}`
|
_: Event | SyntheticEvent<Element, Event>,
|
||||||
);
|
value: number | number[]
|
||||||
|
) => {
|
||||||
|
if (currentQuestion.content.chooseRange && Array.isArray(value)) {
|
||||||
|
if (reversed) {
|
||||||
|
const newMinReversedValue = String(max + min - value[0]);
|
||||||
|
const newMaxReversedValue = String(max + min - value[1]);
|
||||||
|
|
||||||
return;
|
setMinRange(String(value[0]));
|
||||||
}
|
setMaxRange(String(value[1]));
|
||||||
|
setReversedMinRange(newMinReversedValue);
|
||||||
|
setReversedMaxRange(newMaxReversedValue);
|
||||||
|
await sendAnswerToBackend(
|
||||||
|
`${newMinReversedValue}—${newMaxReversedValue}`,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
setMinRange(newValue);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (window.Number(newValue) >= window.Number(maxRange)) {
|
setMinRange(String(value[0]));
|
||||||
updateMinRangeDebounced(`${maxRange}—${maxRange}`, true);
|
setMaxRange(String(value[1]));
|
||||||
|
await sendAnswerToBackend(`${value[0]}—${value[1]}`);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMinRangeDebounced(`${newValue}—${maxRange}`);
|
if (reversed) {
|
||||||
};
|
setReversedInputValue(String(max + min - window.Number(value)));
|
||||||
|
} else {
|
||||||
|
setInputValue(String(value));
|
||||||
|
}
|
||||||
|
|
||||||
const onMaxInputChange = ({ target }: ChangeEvent<HTMLInputElement>) => {
|
await sendAnswerToBackend(String(value));
|
||||||
const newValue = target.value.replace(/\D/g, "");
|
};
|
||||||
|
|
||||||
if (reversed) {
|
const changeValueLabelFormat = (value: number) => {
|
||||||
setReversedMaxRange(newValue);
|
if (!reversed) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
if (window.Number(newValue) >= window.Number(reversedMinRange)) {
|
const [minSliderBorder, maxSliderBorder] = sliderValue
|
||||||
const value = max + min - window.Number(reversedMinRange);
|
.split("—")
|
||||||
updateMaxRangeDebounced(`${value}—${value}`, true);
|
.map(window.Number);
|
||||||
|
|
||||||
return;
|
if (value === minSliderBorder) {
|
||||||
}
|
return max + min - minSliderBorder;
|
||||||
|
}
|
||||||
|
|
||||||
updateMaxRangeDebounced(
|
return max + min - maxSliderBorder;
|
||||||
`${max + min - window.Number(reversedMinRange)}—${newValue}`
|
};
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
const onInputChange = ({ target }: ChangeEvent<HTMLInputElement>) => {
|
||||||
}
|
const value = target.value.replace(/\D/g, "");
|
||||||
|
|
||||||
setMaxRange(newValue);
|
if (reversed) {
|
||||||
|
setReversedInputValue(value);
|
||||||
|
} else {
|
||||||
|
setInputValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
if (window.Number(newValue) <= window.Number(minRange)) {
|
updateValueDebounced(value);
|
||||||
updateMaxRangeDebounced(`${minRange}—${minRange}`, true);
|
};
|
||||||
|
|
||||||
return;
|
const onMinInputChange = ({ target }: ChangeEvent<HTMLInputElement>) => {
|
||||||
}
|
const newValue = target.value.replace(/\D/g, "");
|
||||||
|
|
||||||
updateMaxRangeDebounced(`${minRange}—${newValue}`);
|
if (reversed) {
|
||||||
};
|
setReversedMinRange(newValue);
|
||||||
|
|
||||||
return (
|
if (window.Number(newValue) <= window.Number(reversedMaxRange)) {
|
||||||
<Box>
|
const value = max + min - window.Number(reversedMaxRange);
|
||||||
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
|
updateMinRangeDebounced(`${value}—${value}`, true);
|
||||||
{currentQuestion.title}
|
|
||||||
</Typography>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
width: "100%",
|
|
||||||
marginTop: "20px",
|
|
||||||
gap: "30px",
|
|
||||||
paddingRight: isMobile ? "10px" : undefined,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CustomSlider
|
|
||||||
value={
|
|
||||||
currentQuestion.content.chooseRange
|
|
||||||
? sliderValue.split("—").length || 0 > 1
|
|
||||||
? sliderValue.split("—").map((item) => window.Number(item))
|
|
||||||
: [min, min + 1]
|
|
||||||
: window.Number(sliderValue.split("—")[0])
|
|
||||||
}
|
|
||||||
min={min}
|
|
||||||
max={max}
|
|
||||||
step={currentQuestion.content.step || 1}
|
|
||||||
onChange={onSliderChange}
|
|
||||||
onChangeCommitted={onChangeCommitted}
|
|
||||||
valueLabelFormat={changeValueLabelFormat}
|
|
||||||
sx={{
|
|
||||||
color: theme.palette.primary.main,
|
|
||||||
"& .MuiSlider-valueLabel": {
|
|
||||||
background: theme.palette.primary.main,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{!currentQuestion.content.chooseRange && (
|
return;
|
||||||
<CustomTextField
|
}
|
||||||
placeholder="0"
|
|
||||||
value={reversed ? reversedInputValue : inputValue}
|
|
||||||
onChange={onInputChange}
|
|
||||||
sx={{
|
|
||||||
maxWidth: "80px",
|
|
||||||
borderColor: theme.palette.text.primary,
|
|
||||||
"& .MuiInputBase-input": {
|
|
||||||
textAlign: "center",
|
|
||||||
backgroundColor: quizThemes[settings.cfg.theme].isLight
|
|
||||||
? "white"
|
|
||||||
: theme.palette.background.default,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{currentQuestion.content.chooseRange && (
|
updateMinRangeDebounced(
|
||||||
<Box
|
`${newValue}—${max + min - window.Number(reversedMaxRange)}`
|
||||||
sx={{
|
);
|
||||||
display: "flex",
|
|
||||||
gap: "15px",
|
return;
|
||||||
alignItems: "center",
|
}
|
||||||
"& .MuiFormControl-root": { width: "auto" },
|
|
||||||
}}
|
setMinRange(newValue);
|
||||||
>
|
|
||||||
<CustomTextField
|
if (window.Number(newValue) >= window.Number(maxRange)) {
|
||||||
placeholder="0"
|
updateMinRangeDebounced(`${maxRange}—${maxRange}`, true);
|
||||||
value={reversed ? String(reversedMinRange) : minRange}
|
|
||||||
onChange={onMinInputChange}
|
return;
|
||||||
sx={{
|
}
|
||||||
maxWidth: "80px",
|
|
||||||
borderColor: theme.palette.text.primary,
|
updateMinRangeDebounced(`${newValue}—${maxRange}`);
|
||||||
"& .MuiInputBase-input": {
|
};
|
||||||
textAlign: "center",
|
|
||||||
backgroundColor: quizThemes[settings.cfg.theme].isLight
|
const onMaxInputChange = ({ target }: ChangeEvent<HTMLInputElement>) => {
|
||||||
? "white"
|
const newValue = target.value.replace(/\D/g, "");
|
||||||
: theme.palette.background.default,
|
|
||||||
},
|
if (reversed) {
|
||||||
}}
|
setReversedMaxRange(newValue);
|
||||||
/>
|
|
||||||
<Typography color={theme.palette.text.primary}>до</Typography>
|
if (window.Number(newValue) >= window.Number(reversedMinRange)) {
|
||||||
<CustomTextField
|
const value = max + min - window.Number(reversedMinRange);
|
||||||
placeholder="0"
|
updateMaxRangeDebounced(`${value}—${value}`, true);
|
||||||
value={reversed ? String(reversedMaxRange) : maxRange}
|
|
||||||
onChange={onMaxInputChange}
|
return;
|
||||||
sx={{
|
}
|
||||||
maxWidth: "80px",
|
|
||||||
borderColor: theme.palette.text.primary,
|
updateMaxRangeDebounced(
|
||||||
"& .MuiInputBase-input": {
|
`${max + min - window.Number(reversedMinRange)}—${newValue}`
|
||||||
textAlign: "center",
|
);
|
||||||
backgroundColor: quizThemes[settings.cfg.theme].isLight
|
|
||||||
? "white"
|
return;
|
||||||
: theme.palette.background.default,
|
}
|
||||||
},
|
|
||||||
}}
|
setMaxRange(newValue);
|
||||||
/>
|
|
||||||
</Box>
|
if (window.Number(newValue) <= window.Number(minRange)) {
|
||||||
)}
|
updateMaxRangeDebounced(`${minRange}—${minRange}`, true);
|
||||||
</Box>
|
|
||||||
</Box>
|
return;
|
||||||
);
|
}
|
||||||
|
|
||||||
|
updateMaxRangeDebounced(`${minRange}—${newValue}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Typography
|
||||||
|
variant="h5"
|
||||||
|
color={theme.palette.text.primary}
|
||||||
|
sx={{ wordBreak: "break-word" }}
|
||||||
|
>
|
||||||
|
{currentQuestion.title}
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
marginTop: "20px",
|
||||||
|
gap: "30px",
|
||||||
|
paddingRight: isMobile ? "10px" : undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CustomSlider
|
||||||
|
value={
|
||||||
|
currentQuestion.content.chooseRange
|
||||||
|
? sliderValue.split("—").length || 0 > 1
|
||||||
|
? sliderValue.split("—").map((item) => window.Number(item))
|
||||||
|
: [min, min + 1]
|
||||||
|
: window.Number(sliderValue.split("—")[0])
|
||||||
|
}
|
||||||
|
min={min}
|
||||||
|
max={max}
|
||||||
|
step={currentQuestion.content.step || 1}
|
||||||
|
onChange={onSliderChange}
|
||||||
|
onChangeCommitted={onChangeCommitted}
|
||||||
|
valueLabelFormat={changeValueLabelFormat}
|
||||||
|
sx={{
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
"& .MuiSlider-valueLabel": {
|
||||||
|
background: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{!currentQuestion.content.chooseRange && (
|
||||||
|
<CustomTextField
|
||||||
|
placeholder="0"
|
||||||
|
value={reversed ? reversedInputValue : inputValue}
|
||||||
|
onChange={onInputChange}
|
||||||
|
sx={{
|
||||||
|
maxWidth: "80px",
|
||||||
|
borderColor: theme.palette.text.primary,
|
||||||
|
"& .MuiOutlinedInput-root": { background: "transparent" },
|
||||||
|
"& .MuiInputBase-input": { textAlign: "center", zIndex: 1 },
|
||||||
|
"& .MuiOutlinedInput-notchedOutline": {
|
||||||
|
backgroundColor: quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "white"
|
||||||
|
: theme.palette.background.default,
|
||||||
|
borderColor: "#9A9AAF"
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{currentQuestion.content.chooseRange && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
gap: "15px",
|
||||||
|
alignItems: "center",
|
||||||
|
"& .MuiFormControl-root": { width: "auto" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CustomTextField
|
||||||
|
placeholder="0"
|
||||||
|
value={reversed ? String(reversedMinRange) : minRange}
|
||||||
|
onChange={onMinInputChange}
|
||||||
|
sx={{
|
||||||
|
maxWidth: "80px",
|
||||||
|
borderColor: theme.palette.text.primary,
|
||||||
|
"& .MuiOutlinedInput-root": { background: "transparent" },
|
||||||
|
"& .MuiInputBase-input": { textAlign: "center", zIndex: 1 },
|
||||||
|
"& .MuiOutlinedInput-notchedOutline": {
|
||||||
|
backgroundColor: quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "white"
|
||||||
|
: theme.palette.background.default,
|
||||||
|
borderColor: "#9A9AAF"
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography color={theme.palette.text.primary}>до</Typography>
|
||||||
|
<CustomTextField
|
||||||
|
placeholder="0"
|
||||||
|
value={reversed ? String(reversedMaxRange) : maxRange}
|
||||||
|
onChange={onMaxInputChange}
|
||||||
|
sx={{
|
||||||
|
maxWidth: "80px",
|
||||||
|
"& .MuiOutlinedInput-root": { background: "transparent" },
|
||||||
|
"& .MuiInputBase-input": { textAlign: "center", zIndex: 1 },
|
||||||
|
"& .MuiOutlinedInput-notchedOutline": {
|
||||||
|
backgroundColor: quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "white"
|
||||||
|
: theme.palette.background.default,
|
||||||
|
borderColor: "#9A9AAF"
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,74 +9,87 @@ import { enqueueSnackbar } from "notistack";
|
|||||||
import type { QuizQuestionSelect } from "../../../model/questionTypes/select";
|
import type { QuizQuestionSelect } from "../../../model/questionTypes/select";
|
||||||
import { useQuizData } from "@contexts/QuizDataContext";
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
|
|
||||||
type SelectProps = {
|
type SelectProps = {
|
||||||
currentQuestion: QuizQuestionSelect;
|
currentQuestion: QuizQuestionSelect;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Select = ({ currentQuestion }: SelectProps) => {
|
export const Select = ({ currentQuestion }: SelectProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { quizId } = useQuizData();
|
const { quizId, settings } = useQuizData();
|
||||||
const [isSending, setIsSending] = useState<boolean>(false);
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
const { answers } = useQuizViewStore();
|
const { answers } = useQuizViewStore();
|
||||||
const { answer } =
|
const { answer } =
|
||||||
answers.find(
|
answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
|
||||||
({ questionId }) => questionId === currentQuestion.id
|
|
||||||
) ?? {};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>{currentQuestion.title}</Typography>
|
<Typography
|
||||||
<Box
|
variant="h5"
|
||||||
sx={{
|
color={theme.palette.text.primary}
|
||||||
display: "flex",
|
sx={{ wordBreak: "break-word" }}
|
||||||
flexDirection: "column",
|
>
|
||||||
width: "100%",
|
{currentQuestion.title}
|
||||||
marginTop: "20px",
|
</Typography>
|
||||||
}}
|
<Box
|
||||||
>
|
sx={{
|
||||||
<SelectComponent
|
display: "flex",
|
||||||
disabled={isSending}
|
flexDirection: "column",
|
||||||
placeholder={currentQuestion.content.default}
|
width: "100%",
|
||||||
activeItemIndex={answer ? Number(answer) : -1}
|
marginTop: "20px",
|
||||||
items={currentQuestion.content.variants.map(({ answer }) => answer)}
|
}}
|
||||||
colorMain={theme.palette.primary.main}
|
>
|
||||||
onChange={async (_, value) => {
|
<SelectComponent
|
||||||
setIsSending(true);
|
disabled={isSending}
|
||||||
if (value < 0) {
|
placeholder={currentQuestion.content.default}
|
||||||
deleteAnswer(currentQuestion.id);
|
activeItemIndex={answer ? Number(answer) : -1}
|
||||||
try {
|
items={currentQuestion.content.variants.map(({ answer }) => answer)}
|
||||||
|
colorMain={theme.palette.primary.main}
|
||||||
|
sx={{
|
||||||
|
"& .MuiSelect-select.MuiSelect-outlined": { zIndex: 1 },
|
||||||
|
"& .MuiOutlinedInput-notchedOutline": {
|
||||||
|
background: settings.cfg.design
|
||||||
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "#F2F3F7"
|
||||||
|
: "rgba(154,154,175, 0.2)"
|
||||||
|
: "transparent",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onChange={async (_, value) => {
|
||||||
|
setIsSending(true);
|
||||||
|
if (value < 0) {
|
||||||
|
deleteAnswer(currentQuestion.id);
|
||||||
|
try {
|
||||||
|
await sendAnswer({
|
||||||
|
questionId: currentQuestion.id,
|
||||||
|
body: "",
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
|
}
|
||||||
|
return setIsSending(false);
|
||||||
|
}
|
||||||
|
|
||||||
await sendAnswer({
|
try {
|
||||||
questionId: currentQuestion.id,
|
await sendAnswer({
|
||||||
body: "",
|
questionId: currentQuestion.id,
|
||||||
qid: quizId,
|
body: String(
|
||||||
});
|
currentQuestion.content.variants[Number(value)].answer
|
||||||
|
),
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
|
||||||
} catch (e) {
|
updateAnswer(currentQuestion.id, String(value), 0);
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
} catch (e) {
|
||||||
}
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
return setIsSending(false);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
setIsSending(false);
|
||||||
|
}}
|
||||||
await sendAnswer({
|
/>
|
||||||
questionId: currentQuestion.id,
|
</Box>
|
||||||
body: String(currentQuestion.content.variants[Number(value)].answer),
|
</Box>
|
||||||
qid: quizId,
|
);
|
||||||
});
|
|
||||||
|
|
||||||
updateAnswer(currentQuestion.id, String(value), 0);
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsSending(false);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,10 @@
|
|||||||
import {Box, TextField as MuiTextField, TextFieldProps, Typography, useTheme} from "@mui/material";
|
import {
|
||||||
|
Box,
|
||||||
|
TextField as MuiTextField,
|
||||||
|
TextFieldProps,
|
||||||
|
Typography,
|
||||||
|
useTheme,
|
||||||
|
} from "@mui/material";
|
||||||
|
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
|
|
||||||
@ -8,194 +14,272 @@ import { sendAnswer } from "@api/quizRelase";
|
|||||||
import { useQuizData } from "@contexts/QuizDataContext";
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
|
import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
|
||||||
import { enqueueSnackbar } from "notistack";
|
import { enqueueSnackbar } from "notistack";
|
||||||
import {ChangeEvent, FC, useEffect, useState} from "react";
|
import { ChangeEvent, FC, useEffect, useState } from "react";
|
||||||
import { useDebouncedCallback } from "use-debounce";
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
import type { QuizQuestionText } from "../../../model/questionTypes/text";
|
import type { QuizQuestionText } from "../../../model/questionTypes/text";
|
||||||
|
|
||||||
const TextField = MuiTextField as unknown as FC<TextFieldProps>; // temporary fix ts(2590)
|
const TextField = MuiTextField as unknown as FC<TextFieldProps>; // temporary fix ts(2590)
|
||||||
|
|
||||||
type TextProps = {
|
type TextProps = {
|
||||||
currentQuestion: QuizQuestionText;
|
currentQuestion: QuizQuestionText;
|
||||||
stepNumber: number | null;
|
stepNumber: number | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Orientation = [
|
const Orientation = [
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: false},
|
{ horizontal: false },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: false},
|
{ horizontal: false },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: false},
|
{ horizontal: false },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: false},
|
{ horizontal: false },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: false},
|
{ horizontal: false },
|
||||||
{horizontal: false},
|
{ horizontal: false },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
{horizontal: true},
|
{ horizontal: true },
|
||||||
]
|
];
|
||||||
|
|
||||||
export const Text = ({ currentQuestion, stepNumber }: TextProps) => {
|
export const Text = ({ currentQuestion, stepNumber }: TextProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { settings } = useQuizData();
|
const { settings } = useQuizData();
|
||||||
const spec = settings.cfg.spec
|
const spec = settings.cfg.spec;
|
||||||
const { quizId } = useQuizData();
|
const { quizId } = useQuizData();
|
||||||
const { answers } = useQuizViewStore();
|
const { answers } = useQuizViewStore();
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
|
const { answer } =
|
||||||
const [isSending, setIsSending] = useState<boolean>(false);
|
answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
|
||||||
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
|
|
||||||
const inputHC = useDebouncedCallback(async (text) => {
|
const inputHC = useDebouncedCallback(async (text) => {
|
||||||
setIsSending(true);
|
setIsSending(true);
|
||||||
try {
|
try {
|
||||||
await sendAnswer({
|
await sendAnswer({
|
||||||
questionId: currentQuestion.id,
|
questionId: currentQuestion.id,
|
||||||
body: text,
|
body: text,
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
}
|
|
||||||
|
|
||||||
setIsSending(false);
|
|
||||||
}, 400);
|
|
||||||
useEffect(
|
|
||||||
() => () => {
|
|
||||||
inputHC.flush();
|
|
||||||
},
|
|
||||||
[inputHC]
|
|
||||||
);
|
|
||||||
switch (spec) {
|
|
||||||
case true:
|
|
||||||
return <TextSpecial currentQuestion={currentQuestion} answer={answer} inputHC={inputHC} stepNumber={stepNumber}/>;
|
|
||||||
case undefined:
|
|
||||||
return <TextNormal currentQuestion={currentQuestion} answer={answer} inputHC={inputHC} />;
|
|
||||||
default:
|
|
||||||
return <TextNormal currentQuestion={currentQuestion} answer={answer} inputHC={inputHC} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsSending(false);
|
||||||
|
}, 400);
|
||||||
|
useEffect(
|
||||||
|
() => () => {
|
||||||
|
inputHC.flush();
|
||||||
|
},
|
||||||
|
[inputHC]
|
||||||
|
);
|
||||||
|
switch (spec) {
|
||||||
|
case true:
|
||||||
|
return (
|
||||||
|
<TextSpecial
|
||||||
|
currentQuestion={currentQuestion}
|
||||||
|
answer={answer}
|
||||||
|
inputHC={inputHC}
|
||||||
|
stepNumber={stepNumber}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case undefined:
|
||||||
|
return (
|
||||||
|
<TextNormal
|
||||||
|
currentQuestion={currentQuestion}
|
||||||
|
answer={answer}
|
||||||
|
inputHC={inputHC}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<TextNormal
|
||||||
|
currentQuestion={currentQuestion}
|
||||||
|
answer={answer}
|
||||||
|
inputHC={inputHC}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
currentQuestion: QuizQuestionText;
|
currentQuestion: QuizQuestionText;
|
||||||
answer: any,
|
answer: any;
|
||||||
inputHC: (a: string) => void;
|
inputHC: (a: string) => void;
|
||||||
stepNumber?: number | null;
|
stepNumber?: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TextNormal = ({currentQuestion, answer, inputHC}: Props) => {
|
const TextNormal = ({ currentQuestion, answer, inputHC }: Props) => {
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
return(
|
const { settings } = useQuizData();
|
||||||
<Box>
|
|
||||||
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>{currentQuestion.title}</Typography>
|
return (
|
||||||
|
<Box>
|
||||||
|
<Typography
|
||||||
|
variant="h5"
|
||||||
|
color={theme.palette.text.primary}
|
||||||
|
sx={{ wordBreak: "break-word" }}
|
||||||
|
>
|
||||||
|
{currentQuestion.title}
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
width: "100%",
|
||||||
|
marginTop: "20px",
|
||||||
|
flexDirection: isMobile ? "column-reverse" : undefined,
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CustomTextField
|
||||||
|
placeholder={currentQuestion.content.placeholder}
|
||||||
|
value={answer || ""}
|
||||||
|
onChange={async ({ target }) => {
|
||||||
|
updateAnswer(currentQuestion.id, target.value, 0);
|
||||||
|
inputHC(target.value);
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
"& .MuiOutlinedInput-root": {
|
||||||
|
background: settings.cfg.design
|
||||||
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "#F2F3F7"
|
||||||
|
: "rgba(154,154,175, 0.2)"
|
||||||
|
: "transparent",
|
||||||
|
},
|
||||||
|
"& .MuiOutlinedInput-notchedOutline": {
|
||||||
|
borderColor: "#9A9AAF"
|
||||||
|
},
|
||||||
|
"&:focus-visible": { borderColor: theme.palette.primary.main },
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{currentQuestion.content.back &&
|
||||||
|
currentQuestion.content.back !== " " && (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
maxWidth: "400px",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
marginTop: "20px",
|
height: "300px",
|
||||||
flexDirection: isMobile ? "column-reverse" : undefined,
|
margin: "15px",
|
||||||
alignItems: "center"
|
}}
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<CustomTextField
|
<img
|
||||||
placeholder={currentQuestion.content.placeholder}
|
key={currentQuestion.id}
|
||||||
value={answer || ""}
|
src={currentQuestion.content.back}
|
||||||
onChange={async ({ target }) => {
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
updateAnswer(currentQuestion.id, target.value, 0);
|
alt=""
|
||||||
inputHC(target.value);
|
/>
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
"&:focus-visible": {
|
|
||||||
borderColor: theme.palette.primary.main
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{currentQuestion.content.back && currentQuestion.content.back !== " " && (
|
|
||||||
<Box sx={{ maxWidth: "400px", width: "100%", height: "300px", margin: "15px" }}>
|
|
||||||
<img
|
|
||||||
key={currentQuestion.id}
|
|
||||||
src={currentQuestion.content.back}
|
|
||||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
)}
|
||||||
)
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const TextSpecial = ({currentQuestion, answer, inputHC, stepNumber}: Props) => {
|
const TextSpecial = ({
|
||||||
const theme = useTheme();
|
currentQuestion,
|
||||||
const isMobile = useRootContainerSize() < 650;
|
answer,
|
||||||
const isHorizontal = Orientation[Number(stepNumber) -1].horizontal
|
inputHC,
|
||||||
return(
|
stepNumber,
|
||||||
<Box sx={{display: "flex", flexDirection: isMobile? "column" : undefined, alignItems: isMobile ? "center" : undefined,}}>
|
}: Props) => {
|
||||||
<Box
|
const theme = useTheme();
|
||||||
sx={{
|
const isMobile = useRootContainerSize() < 650;
|
||||||
display: "flex",
|
const isHorizontal = Orientation[Number(stepNumber) - 1].horizontal;
|
||||||
width: "100%",
|
const { settings } = useQuizData();
|
||||||
marginTop: "20px",
|
|
||||||
flexDirection: "column",
|
return (
|
||||||
alignItems: "center",
|
<Box
|
||||||
gap: "20px"
|
sx={{
|
||||||
}}
|
display: "flex",
|
||||||
>
|
flexDirection: isMobile ? "column" : undefined,
|
||||||
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>{currentQuestion.title}</Typography>
|
alignItems: isMobile ? "center" : undefined,
|
||||||
{isHorizontal && currentQuestion.content.back && currentQuestion.content.back !== " " && (
|
}}
|
||||||
<Box sx={{margin: "30px", width: "50vw", maxHeight: "550px" }}>
|
>
|
||||||
<img
|
<Box
|
||||||
key={currentQuestion.id}
|
sx={{
|
||||||
src={currentQuestion.content.back}
|
display: "flex",
|
||||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
width: "100%",
|
||||||
alt=""
|
marginTop: "20px",
|
||||||
/>
|
flexDirection: "column",
|
||||||
</Box>
|
alignItems: "center",
|
||||||
)}
|
gap: "20px",
|
||||||
{
|
}}
|
||||||
(<TextField
|
>
|
||||||
autoFocus={true}
|
<Typography
|
||||||
multiline
|
variant="h5"
|
||||||
maxRows={4}
|
color={theme.palette.text.primary}
|
||||||
placeholder={currentQuestion.content.placeholder}
|
sx={{ wordBreak: "break-word" }}
|
||||||
value={answer || ""}
|
>
|
||||||
onChange={async ({ target }:ChangeEvent<HTMLInputElement>) => {
|
{currentQuestion.title}
|
||||||
updateAnswer(currentQuestion.id, target.value, 0);
|
</Typography>
|
||||||
inputHC(target.value);
|
{isHorizontal &&
|
||||||
}
|
currentQuestion.content.back &&
|
||||||
}
|
currentQuestion.content.back !== " " && (
|
||||||
inputProps={{maxLength:400}}
|
<Box sx={{ margin: "30px", width: "50vw", maxHeight: "550px" }}>
|
||||||
sx={{
|
<img
|
||||||
width: "100%",
|
key={currentQuestion.id}
|
||||||
"&:focus-visible": {
|
src={currentQuestion.content.back}
|
||||||
borderColor: theme.palette.primary.main
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
}
|
alt=""
|
||||||
}}
|
/>
|
||||||
/>)
|
|
||||||
}
|
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
{!isHorizontal && currentQuestion.content.back && currentQuestion.content.back !== " " && (
|
)}
|
||||||
<Box sx={{margin: "15px", width: "40vw" }}>
|
{
|
||||||
<img
|
<TextField
|
||||||
key={currentQuestion.id}
|
autoFocus={true}
|
||||||
src={currentQuestion.content.back}
|
multiline
|
||||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
maxRows={4}
|
||||||
alt=""
|
placeholder={currentQuestion.content.placeholder}
|
||||||
/>
|
value={answer || ""}
|
||||||
</Box>
|
onChange={async ({ target }: ChangeEvent<HTMLInputElement>) => {
|
||||||
)}
|
updateAnswer(currentQuestion.id, target.value, 0);
|
||||||
</Box>
|
inputHC(target.value);
|
||||||
)
|
}}
|
||||||
}
|
inputProps={{
|
||||||
|
maxLength: 400,
|
||||||
|
background: settings.cfg.design
|
||||||
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "#F2F3F7"
|
||||||
|
: "rgba(154,154,175, 0.2)"
|
||||||
|
: "transparent",
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
"& .MuiOutlinedInput-root": {
|
||||||
|
backgroundColor: settings.cfg.design
|
||||||
|
? "rgba(154,154,175, 0.2)"
|
||||||
|
: "#FFFFFF",
|
||||||
|
},
|
||||||
|
"&:focus-visible": {
|
||||||
|
borderColor: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</Box>
|
||||||
|
{!isHorizontal &&
|
||||||
|
currentQuestion.content.back &&
|
||||||
|
currentQuestion.content.back !== " " && (
|
||||||
|
<Box sx={{ margin: "15px", width: "40vw" }}>
|
||||||
|
<img
|
||||||
|
key={currentQuestion.id}
|
||||||
|
src={currentQuestion.content.back}
|
||||||
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@ -1,22 +1,22 @@
|
|||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
FormGroup,
|
FormGroup,
|
||||||
TextField as MuiTextField,
|
TextField as MuiTextField,
|
||||||
Radio,
|
Radio,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
TextFieldProps,
|
TextFieldProps,
|
||||||
Typography,
|
Typography,
|
||||||
useTheme
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { FC, useEffect, useState } from "react";
|
import { FC, useEffect, useState } from "react";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
deleteAnswer,
|
deleteAnswer,
|
||||||
updateAnswer,
|
updateAnswer,
|
||||||
updateOwnVariant,
|
updateOwnVariant,
|
||||||
useQuizViewStore
|
useQuizViewStore,
|
||||||
} from "@stores/quizView";
|
} from "@stores/quizView";
|
||||||
|
|
||||||
import { CheckboxIcon } from "@icons/Checkbox";
|
import { CheckboxIcon } from "@icons/Checkbox";
|
||||||
@ -36,245 +36,263 @@ import moment from "moment";
|
|||||||
const TextField = MuiTextField as unknown as FC<TextFieldProps>;
|
const TextField = MuiTextField as unknown as FC<TextFieldProps>;
|
||||||
|
|
||||||
type VariantProps = {
|
type VariantProps = {
|
||||||
currentQuestion: QuizQuestionVariant;
|
currentQuestion: QuizQuestionVariant;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Variant = ({ currentQuestion }: VariantProps) => {
|
export const Variant = ({ currentQuestion }: VariantProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
const { answers, ownVariants } = useQuizViewStore();
|
const { answers, ownVariants } = useQuizViewStore();
|
||||||
const { answer } =
|
const { answer } =
|
||||||
answers.find(
|
answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
|
||||||
({ questionId }) => questionId === currentQuestion.id
|
const ownVariant = ownVariants.find(
|
||||||
) ?? {};
|
(variant) => variant.id === currentQuestion.id
|
||||||
const ownVariant = ownVariants.find(
|
);
|
||||||
(variant) => variant.id === currentQuestion.id
|
|
||||||
);
|
|
||||||
|
|
||||||
const [isSending, setIsSending] = useState(false);
|
const [isSending, setIsSending] = useState(false);
|
||||||
|
|
||||||
const Group = currentQuestion.content.multi ? FormGroup : RadioGroup;
|
const Group = currentQuestion.content.multi ? FormGroup : RadioGroup;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ownVariant) {
|
if (!ownVariant) {
|
||||||
updateOwnVariant(currentQuestion.id, "");
|
updateOwnVariant(currentQuestion.id, "");
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question");
|
if (moment.isMoment(answer))
|
||||||
|
throw new Error("Answer is Moment in Variant question");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>{currentQuestion.title}</Typography>
|
<Typography
|
||||||
<Box sx={{
|
variant="h5"
|
||||||
display: "flex", gap: "20px",
|
color={theme.palette.text.primary}
|
||||||
flexDirection: isMobile ? "column-reverse" : undefined, alignItems: isMobile ? "center" : undefined
|
sx={{ wordBreak: "break-word" }}
|
||||||
}}>
|
>
|
||||||
<Group
|
{currentQuestion.title}
|
||||||
name={currentQuestion.id.toString()}
|
</Typography>
|
||||||
value={currentQuestion.content.variants.findIndex(
|
<Box
|
||||||
({ id }) => answer === id
|
sx={{
|
||||||
)}
|
display: "flex",
|
||||||
sx={{
|
gap: "20px",
|
||||||
display: "flex",
|
flexDirection: isMobile ? "column-reverse" : undefined,
|
||||||
flexWrap: "wrap",
|
alignItems: isMobile ? "center" : undefined,
|
||||||
flexDirection: "row",
|
}}
|
||||||
justifyContent: "space-between",
|
>
|
||||||
flexBasis: "100%",
|
<Group
|
||||||
marginTop: "20px",
|
name={currentQuestion.id.toString()}
|
||||||
width: isMobile ? "100%" : undefined
|
value={currentQuestion.content.variants.findIndex(
|
||||||
}}
|
({ id }) => answer === id
|
||||||
>
|
)}
|
||||||
<Box
|
sx={{
|
||||||
sx={{
|
display: "flex",
|
||||||
display: "flex",
|
flexWrap: "wrap",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
flexWrap: "wrap",
|
justifyContent: "space-between",
|
||||||
width: "100%",
|
flexBasis: "100%",
|
||||||
gap: "20px",
|
marginTop: "20px",
|
||||||
}}
|
width: isMobile ? "100%" : undefined,
|
||||||
>
|
}}
|
||||||
{currentQuestion.content.variants.map((variant, index) => (
|
>
|
||||||
<VariantItem
|
<Box
|
||||||
key={variant.id}
|
sx={{
|
||||||
currentQuestion={currentQuestion}
|
display: "flex",
|
||||||
variant={variant}
|
flexDirection: "row",
|
||||||
answer={answer}
|
flexWrap: "wrap",
|
||||||
index={index}
|
width: "100%",
|
||||||
isSending={isSending}
|
gap: "20px",
|
||||||
setIsSending={setIsSending}
|
}}
|
||||||
/>
|
>
|
||||||
))}
|
{currentQuestion.content.variants.map((variant, index) => (
|
||||||
{currentQuestion.content.own && ownVariant && (
|
<VariantItem
|
||||||
<VariantItem
|
key={variant.id}
|
||||||
own
|
currentQuestion={currentQuestion}
|
||||||
currentQuestion={currentQuestion}
|
variant={variant}
|
||||||
variant={ownVariant.variant}
|
answer={answer}
|
||||||
answer={answer}
|
index={index}
|
||||||
index={currentQuestion.content.variants.length + 2}
|
isSending={isSending}
|
||||||
isSending={isSending}
|
setIsSending={setIsSending}
|
||||||
setIsSending={setIsSending}
|
/>
|
||||||
/>
|
))}
|
||||||
)}
|
{currentQuestion.content.own && ownVariant && (
|
||||||
</Box>
|
<VariantItem
|
||||||
</Group>
|
own
|
||||||
{currentQuestion.content.back && currentQuestion.content.back !== " " && (
|
currentQuestion={currentQuestion}
|
||||||
<Box sx={{ maxWidth: "400px", width: "100%", height: "300px" }}>
|
variant={ownVariant.variant}
|
||||||
<img
|
answer={answer}
|
||||||
key={currentQuestion.id}
|
index={currentQuestion.content.variants.length + 2}
|
||||||
src={currentQuestion.content.back}
|
isSending={isSending}
|
||||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
setIsSending={setIsSending}
|
||||||
alt=""
|
/>
|
||||||
/>
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
</Group>
|
||||||
|
{currentQuestion.content.back &&
|
||||||
|
currentQuestion.content.back !== " " && (
|
||||||
|
<Box sx={{ maxWidth: "400px", width: "100%", height: "300px" }}>
|
||||||
|
<img
|
||||||
|
key={currentQuestion.id}
|
||||||
|
src={currentQuestion.content.back}
|
||||||
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
)}
|
||||||
);
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const VariantItem = ({
|
const VariantItem = ({
|
||||||
currentQuestion,
|
currentQuestion,
|
||||||
variant,
|
variant,
|
||||||
answer,
|
answer,
|
||||||
index,
|
index,
|
||||||
own = false,
|
own = false,
|
||||||
isSending,
|
isSending,
|
||||||
setIsSending,
|
setIsSending,
|
||||||
}: {
|
}: {
|
||||||
currentQuestion: QuizQuestionVariant;
|
currentQuestion: QuizQuestionVariant;
|
||||||
variant: QuestionVariant;
|
variant: QuestionVariant;
|
||||||
answer: string | string[] | undefined;
|
answer: string | string[] | undefined;
|
||||||
index: number;
|
index: number;
|
||||||
own?: boolean;
|
own?: boolean;
|
||||||
isSending: boolean;
|
isSending: boolean;
|
||||||
setIsSending: (a: boolean) => void;
|
setIsSending: (a: boolean) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { settings, quizId } = useQuizData();
|
const { settings, quizId } = useQuizData();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
key={variant.id}
|
key={variant.id}
|
||||||
disabled={isSending}
|
disabled={isSending}
|
||||||
sx={{
|
sx={{
|
||||||
margin: "0",
|
margin: "0",
|
||||||
borderRadius: "12px",
|
borderRadius: "12px",
|
||||||
color: theme.palette.text.primary,
|
color: theme.palette.text.primary,
|
||||||
padding: "15px",
|
padding: "15px",
|
||||||
border: `1px solid`,
|
border: `1px solid`,
|
||||||
borderColor: answer === variant.id
|
borderColor:
|
||||||
? theme.palette.primary.main
|
answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
|
||||||
: "#9A9AAF",
|
backgroundColor: settings.cfg.design
|
||||||
backgroundColor: quizThemes[settings.cfg.theme].isLight
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
? "white"
|
? "#FFFFFF"
|
||||||
: theme.palette.background.default,
|
: "rgba(154,154,175, 0.2)"
|
||||||
display: "flex",
|
: quizThemes[settings.cfg.theme].isLight
|
||||||
maxWidth: "685px",
|
? "white"
|
||||||
maxHeight: "85px",
|
: theme.palette.background.default,
|
||||||
justifyContent: "space-between",
|
display: "flex",
|
||||||
width: "100%",
|
maxWidth: "685px",
|
||||||
"&.MuiFormControl-root": {
|
maxHeight: "85px",
|
||||||
width: "100%",
|
justifyContent: "space-between",
|
||||||
},
|
width: "100%",
|
||||||
"& .MuiFormControlLabel-label": {
|
"&.MuiFormControl-root": {
|
||||||
wordBreak: "break-word",
|
width: "100%",
|
||||||
height: variant.answer.length <= 60 ? undefined : "60px",
|
},
|
||||||
overflow: "auto",
|
"& .MuiFormControlLabel-label": {
|
||||||
lineHeight: "normal",
|
wordBreak: "break-word",
|
||||||
"&::-webkit-scrollbar": {
|
height: variant.answer.length <= 60 ? undefined : "60px",
|
||||||
width: "4px",
|
overflow: "auto",
|
||||||
},
|
lineHeight: "normal",
|
||||||
"&::-webkit-scrollbar-thumb": {
|
"&::-webkit-scrollbar": {
|
||||||
backgroundColor: "#b8babf",
|
width: "4px",
|
||||||
}
|
},
|
||||||
}
|
"&::-webkit-scrollbar-thumb": {
|
||||||
}}
|
backgroundColor: "#b8babf",
|
||||||
value={index}
|
},
|
||||||
labelPlacement="start"
|
},
|
||||||
control={
|
}}
|
||||||
currentQuestion.content.multi ?
|
value={index}
|
||||||
<Checkbox
|
labelPlacement="start"
|
||||||
checked={!!answer?.includes(variant.id)}
|
control={
|
||||||
checkedIcon={<CheckboxIcon checked color={theme.palette.primary.main} />}
|
currentQuestion.content.multi ? (
|
||||||
icon={<CheckboxIcon />}
|
<Checkbox
|
||||||
/>
|
checked={!!answer?.includes(variant.id)}
|
||||||
:
|
checkedIcon={
|
||||||
<Radio checkedIcon={<RadioCheck color={theme.palette.primary.main} />} icon={<RadioIcon />} />
|
<CheckboxIcon checked color={theme.palette.primary.main} />
|
||||||
}
|
}
|
||||||
label={own ? <TextField label="Другое..." /> : variant.answer}
|
icon={<CheckboxIcon />}
|
||||||
onClick={async (event) => {
|
/>
|
||||||
event.preventDefault();
|
) : (
|
||||||
if (isSending) return;
|
<Radio
|
||||||
|
checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
|
||||||
|
icon={<RadioIcon />}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
label={own ? <TextField label="Другое..." /> : variant.answer}
|
||||||
|
onClick={async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
if (isSending) return;
|
||||||
|
|
||||||
setIsSending(true);
|
setIsSending(true);
|
||||||
const variantId = currentQuestion.content.variants[index].id;
|
const variantId = currentQuestion.content.variants[index].id;
|
||||||
console.log(answer);
|
console.log(answer);
|
||||||
|
|
||||||
if (currentQuestion.content.multi) {
|
if (currentQuestion.content.multi) {
|
||||||
const currentAnswer = typeof answer !== "string" ? answer || [] : [];
|
const currentAnswer = typeof answer !== "string" ? answer || [] : [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await sendAnswer({
|
await sendAnswer({
|
||||||
questionId: currentQuestion.id,
|
questionId: currentQuestion.id,
|
||||||
body: currentAnswer.includes(variantId)
|
body: currentAnswer.includes(variantId)
|
||||||
? currentAnswer?.filter((item) => item !== variantId)
|
? currentAnswer?.filter((item) => item !== variantId)
|
||||||
: [...currentAnswer, variantId],
|
: [...currentAnswer, variantId],
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
});
|
});
|
||||||
|
|
||||||
updateAnswer(
|
updateAnswer(
|
||||||
currentQuestion.id,
|
currentQuestion.id,
|
||||||
currentAnswer.includes(variantId)
|
currentAnswer.includes(variantId)
|
||||||
? currentAnswer?.filter((item) => item !== variantId)
|
? currentAnswer?.filter((item) => item !== variantId)
|
||||||
: [...currentAnswer, variantId],
|
: [...currentAnswer, variantId],
|
||||||
currentQuestion.content.variants[index].points || 0
|
currentQuestion.content.variants[index].points || 0
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsSending(false);
|
setIsSending(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await sendAnswer({
|
await sendAnswer({
|
||||||
questionId: currentQuestion.id,
|
questionId: currentQuestion.id,
|
||||||
body: currentQuestion.content.variants[index].answer,
|
body: currentQuestion.content.variants[index].answer,
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
});
|
});
|
||||||
|
|
||||||
updateAnswer(currentQuestion.id, variantId,
|
updateAnswer(
|
||||||
answer === variantId ? 0
|
currentQuestion.id,
|
||||||
:
|
variantId,
|
||||||
currentQuestion.content.variants[index].points || 0
|
answer === variantId
|
||||||
);
|
? 0
|
||||||
|
: currentQuestion.content.variants[index].points || 0
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
|
}
|
||||||
|
|
||||||
} catch (e) {
|
if (answer === variantId) {
|
||||||
console.log(e);
|
try {
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
await sendAnswer({
|
||||||
}
|
questionId: currentQuestion.id,
|
||||||
|
body: "",
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
|
}
|
||||||
|
deleteAnswer(currentQuestion.id);
|
||||||
|
}
|
||||||
|
|
||||||
if (answer === variantId) {
|
setIsSending(false);
|
||||||
try {
|
}}
|
||||||
|
/>
|
||||||
await sendAnswer({
|
);
|
||||||
questionId: currentQuestion.id,
|
|
||||||
body: "",
|
|
||||||
qid: quizId,
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
|
||||||
}
|
|
||||||
deleteAnswer(currentQuestion.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsSending(false);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
Radio,
|
Radio,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
Typography,
|
Typography,
|
||||||
useTheme
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { deleteAnswer, updateAnswer, useQuizViewStore } from "@stores/quizView";
|
import { deleteAnswer, updateAnswer, useQuizViewStore } from "@stores/quizView";
|
||||||
|
|
||||||
@ -21,173 +21,194 @@ import type { QuizQuestionVarImg } from "../../../model/questionTypes/varimg";
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
type VarimgProps = {
|
type VarimgProps = {
|
||||||
currentQuestion: QuizQuestionVarImg;
|
currentQuestion: QuizQuestionVarImg;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Varimg = ({ currentQuestion }: VarimgProps) => {
|
export const Varimg = ({ currentQuestion }: VarimgProps) => {
|
||||||
const { settings, quizId } = useQuizData();
|
const { settings, quizId } = useQuizData();
|
||||||
const { answers } = useQuizViewStore();
|
const { answers } = useQuizViewStore();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
const [isSending, setIsSending] = useState<boolean>(false);
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
|
|
||||||
const { answer } =
|
const { answer } =
|
||||||
answers.find(
|
answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
|
||||||
({ questionId }) => questionId === currentQuestion.id
|
const variant = currentQuestion.content.variants.find(
|
||||||
) ?? {};
|
({ id }) => answer === id
|
||||||
const variant = currentQuestion.content.variants.find(
|
);
|
||||||
({ id }) => answer === id
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>{currentQuestion.title}</Typography>
|
<Typography
|
||||||
<Box sx={{
|
variant="h5"
|
||||||
display: "flex",
|
color={theme.palette.text.primary}
|
||||||
marginTop: "20px",
|
sx={{ wordBreak: "break-word" }}
|
||||||
flexDirection: isMobile ? "column-reverse" : undefined,
|
>
|
||||||
gap: isMobile ? "30px" : undefined,
|
{currentQuestion.title}
|
||||||
alignItems: isMobile ? "center" : undefined
|
</Typography>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
marginTop: "20px",
|
||||||
|
flexDirection: isMobile ? "column-reverse" : undefined,
|
||||||
|
gap: isMobile ? "30px" : undefined,
|
||||||
|
alignItems: isMobile ? "center" : undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RadioGroup
|
||||||
|
name={currentQuestion.id}
|
||||||
|
value={currentQuestion.content.variants.findIndex(
|
||||||
|
({ id }) => answer === id
|
||||||
|
)}
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
flexBasis: "100%",
|
||||||
|
width: isMobile ? "100%" : undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
gap: isMobile ? "20px" : undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{currentQuestion.content.variants.map((variant, index) => (
|
||||||
|
<FormControlLabel
|
||||||
|
key={variant.id}
|
||||||
|
disabled={isSending}
|
||||||
|
sx={{
|
||||||
|
marginBottom: "15px",
|
||||||
|
borderRadius: "5px",
|
||||||
|
padding: "15px",
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
backgroundColor: settings.cfg.design
|
||||||
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "#FFFFFF"
|
||||||
|
: "rgba(154,154,175, 0.2)"
|
||||||
|
: quizThemes[settings.cfg.theme].isLight
|
||||||
|
? "white"
|
||||||
|
: theme.palette.background.default,
|
||||||
|
border: `1px solid`,
|
||||||
|
borderColor:
|
||||||
|
answer === variant.id
|
||||||
|
? theme.palette.primary.main
|
||||||
|
: "#9A9AAF",
|
||||||
|
display: "flex",
|
||||||
|
margin: isMobile ? 0 : undefined,
|
||||||
|
"& .MuiFormControlLabel-label": {
|
||||||
|
wordBreak: "break-word",
|
||||||
|
height: variant.answer.length <= 60 ? undefined : "60px",
|
||||||
|
overflow: "auto",
|
||||||
|
lineHeight: "normal",
|
||||||
|
paddingLeft: "45px",
|
||||||
|
"&::-webkit-scrollbar": {
|
||||||
|
width: "4px",
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb": {
|
||||||
|
backgroundColor: "#b8babf",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
value={index}
|
||||||
|
onClick={async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
}}>
|
setIsSending(true);
|
||||||
<RadioGroup
|
try {
|
||||||
name={currentQuestion.id}
|
await sendAnswer({
|
||||||
value={currentQuestion.content.variants.findIndex(
|
questionId: currentQuestion.id,
|
||||||
({ id }) => answer === id
|
body: `${currentQuestion.content.variants[index].answer} <img style="width:100%; max-width:250px; max-height:250px" src="${currentQuestion.content.variants[index].extendedText}"/>`,
|
||||||
)}
|
qid: quizId,
|
||||||
sx={{
|
});
|
||||||
display: "flex",
|
|
||||||
flexWrap: "wrap",
|
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
flexBasis: "100%",
|
|
||||||
width: isMobile ? "100%" : undefined
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box sx={{ display: "flex", flexDirection: "column", width: "100%", gap: isMobile ? "20px" : undefined }}>
|
|
||||||
{currentQuestion.content.variants.map((variant, index) => (
|
|
||||||
<FormControlLabel
|
|
||||||
key={variant.id}
|
|
||||||
disabled={isSending}
|
|
||||||
sx={{
|
|
||||||
marginBottom: "15px",
|
|
||||||
borderRadius: "5px",
|
|
||||||
padding: "15px",
|
|
||||||
color: theme.palette.text.primary,
|
|
||||||
backgroundColor: quizThemes[settings.cfg.theme].isLight ? "white" : theme.palette.background.default,
|
|
||||||
border: `1px solid`,
|
|
||||||
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
|
|
||||||
display: "flex",
|
|
||||||
margin: isMobile ? 0 : undefined,
|
|
||||||
"& .MuiFormControlLabel-label": {
|
|
||||||
wordBreak: "break-word",
|
|
||||||
height: variant.answer.length <= 60 ? undefined : "60px",
|
|
||||||
overflow: "auto",
|
|
||||||
lineHeight: "normal",
|
|
||||||
paddingLeft: "45px",
|
|
||||||
"&::-webkit-scrollbar": {
|
|
||||||
width: "4px",
|
|
||||||
},
|
|
||||||
"&::-webkit-scrollbar-thumb": {
|
|
||||||
backgroundColor: "#b8babf",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
value={index}
|
|
||||||
onClick={async (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
setIsSending(true);
|
updateAnswer(
|
||||||
try {
|
currentQuestion.id,
|
||||||
|
currentQuestion.content.variants[index].id,
|
||||||
|
currentQuestion.content.variants[index].points || 0
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
|
}
|
||||||
|
|
||||||
await sendAnswer({
|
if (answer === currentQuestion.content.variants[index].id) {
|
||||||
questionId: currentQuestion.id,
|
try {
|
||||||
body: `${currentQuestion.content.variants[index].answer} <img style="width:100%; max-width:250px; max-height:250px" src="${currentQuestion.content.variants[index].extendedText}"/>`,
|
await sendAnswer({
|
||||||
qid: quizId,
|
questionId: currentQuestion.id,
|
||||||
});
|
body: "",
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
|
}
|
||||||
|
deleteAnswer(currentQuestion.id);
|
||||||
|
}
|
||||||
|
|
||||||
updateAnswer(
|
setIsSending(false);
|
||||||
currentQuestion.id,
|
}}
|
||||||
currentQuestion.content.variants[index].id,
|
control={
|
||||||
currentQuestion.content.variants[index].points || 0
|
<Radio
|
||||||
);
|
checkedIcon={
|
||||||
|
<RadioCheck color={theme.palette.primary.main} />
|
||||||
} catch (e) {
|
}
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
icon={<RadioIcon />}
|
||||||
}
|
/>
|
||||||
|
}
|
||||||
|
label={variant.answer}
|
||||||
if (answer === currentQuestion.content.variants[index].id) {
|
/>
|
||||||
try {
|
))}
|
||||||
|
</Box>
|
||||||
await sendAnswer({
|
</RadioGroup>
|
||||||
questionId: currentQuestion.id,
|
{/* {(variant?.extendedText || currentQuestion.content.back) && ( */}
|
||||||
body: "",
|
<Box
|
||||||
qid: quizId,
|
sx={{
|
||||||
});
|
maxWidth: "450px",
|
||||||
|
width: "100%",
|
||||||
} catch (e) {
|
height: "450px",
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
border: "1px solid #9A9AAF",
|
||||||
}
|
borderRadius: "12px",
|
||||||
deleteAnswer(currentQuestion.id);
|
overflow: "hidden",
|
||||||
}
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
setIsSending(false);
|
justifyContent: "center",
|
||||||
}}
|
backgroundColor: "#9A9AAF12",
|
||||||
control={
|
color: theme.palette.text.primary,
|
||||||
<Radio checkedIcon={<RadioCheck color={theme.palette.primary.main} />} icon={<RadioIcon />} />
|
textAlign: "center",
|
||||||
}
|
}}
|
||||||
label={variant.answer}
|
>
|
||||||
/>
|
{answer ? (
|
||||||
))}
|
variant?.extendedText ? (
|
||||||
</Box>
|
<img
|
||||||
</RadioGroup>
|
src={variant?.extendedText}
|
||||||
{/* {(variant?.extendedText || currentQuestion.content.back) && ( */}
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
<Box
|
alt=""
|
||||||
sx={{
|
/>
|
||||||
maxWidth: "450px",
|
) : (
|
||||||
width: "100%",
|
<BlankImage />
|
||||||
height: "450px",
|
)
|
||||||
border: "1px solid #9A9AAF",
|
) : currentQuestion.content.back !== " " &&
|
||||||
borderRadius: "12px",
|
currentQuestion.content.back !== null &&
|
||||||
overflow: "hidden",
|
currentQuestion.content.back.length > 0 ? (
|
||||||
display: "flex",
|
<img
|
||||||
alignItems: "center",
|
src={currentQuestion.content.back}
|
||||||
justifyContent: "center",
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
backgroundColor: "#9A9AAF12",
|
alt=""
|
||||||
color: "#9A9AAF",
|
/>
|
||||||
textAlign: "center"
|
) : currentQuestion.content.replText !== " " &&
|
||||||
}}
|
currentQuestion.content.replText.length > 0 ? (
|
||||||
>
|
currentQuestion.content.replText
|
||||||
{answer ? (
|
) : variant?.extendedText || isMobile ? (
|
||||||
variant?.extendedText ? (
|
"Выберите вариант ответа ниже"
|
||||||
<img
|
) : (
|
||||||
src={variant?.extendedText}
|
"Выберите вариант ответа слева"
|
||||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
)}
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<BlankImage />
|
|
||||||
)
|
|
||||||
) : currentQuestion.content.back !== " "
|
|
||||||
&& currentQuestion.content.back !== null
|
|
||||||
&& currentQuestion.content.back.length > 0
|
|
||||||
? (
|
|
||||||
<img
|
|
||||||
src={currentQuestion.content.back}
|
|
||||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
) : (currentQuestion.content.replText !== " " && currentQuestion.content.replText.length > 0) ? currentQuestion.content.replText : variant?.extendedText || isMobile ? (
|
|
||||||
"Выберите вариант ответа ниже"
|
|
||||||
) : (
|
|
||||||
"Выберите вариант ответа слева"
|
|
||||||
)}
|
|
||||||
|
|
||||||
</Box>
|
|
||||||
{/* )} */}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
{/* )} */}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -121,8 +121,7 @@ export const Select = ({
|
|||||||
"& .MuiTypography-root": {
|
"& .MuiTypography-root": {
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
textOverflow: "ellipsis",
|
textOverflow: "ellipsis",
|
||||||
}
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
IconComponent={(props) => <ArrowDown {...props} />}
|
IconComponent={(props) => <ArrowDown {...props} />}
|
||||||
@ -139,7 +138,7 @@ export const Select = ({
|
|||||||
borderRadius: "5px",
|
borderRadius: "5px",
|
||||||
color: colorPlaceholder,
|
color: colorPlaceholder,
|
||||||
whiteSpace: "normal",
|
whiteSpace: "normal",
|
||||||
wordBreak: "break-word"
|
wordBreak: "break-word",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{item}
|
{item}
|
||||||
|
|||||||
@ -11,115 +11,126 @@ export type QuizResultsType = true | null;
|
|||||||
export type QuizStep = "startpage" | "question" | "contactform";
|
export type QuizStep = "startpage" | "question" | "contactform";
|
||||||
|
|
||||||
export type QuizTheme =
|
export type QuizTheme =
|
||||||
| "StandardTheme"
|
| "StandardTheme"
|
||||||
| "StandardDarkTheme"
|
| "StandardDarkTheme"
|
||||||
| "PinkTheme"
|
| "PinkTheme"
|
||||||
| "PinkDarkTheme"
|
| "PinkDarkTheme"
|
||||||
| "BlackWhiteTheme"
|
| "BlackWhiteTheme"
|
||||||
| "OliveTheme"
|
| "OliveTheme"
|
||||||
| "YellowTheme"
|
| "YellowTheme"
|
||||||
| "GoldDarkTheme"
|
| "GoldDarkTheme"
|
||||||
| "PurpleTheme"
|
| "PurpleTheme"
|
||||||
| "BlueTheme"
|
| "BlueTheme"
|
||||||
| "BlueDarkTheme";
|
| "BlueDarkTheme"
|
||||||
|
| "Design1"
|
||||||
|
| "Design2"
|
||||||
|
| "Design3"
|
||||||
|
| "Design4"
|
||||||
|
| "Design5"
|
||||||
|
| "Design6"
|
||||||
|
| "Design7"
|
||||||
|
| "Design8"
|
||||||
|
| "Design9"
|
||||||
|
| "Design10";
|
||||||
|
|
||||||
export type FCField = {
|
export type FCField = {
|
||||||
text: string;
|
text: string;
|
||||||
innerText: string;
|
innerText: string;
|
||||||
key: string;
|
key: string;
|
||||||
required: boolean;
|
required: boolean;
|
||||||
used: boolean;
|
used: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type QuizSettings = {
|
export type QuizSettings = {
|
||||||
questions: AnyTypedQuizQuestion[];
|
questions: AnyTypedQuizQuestion[];
|
||||||
settings: {
|
settings: {
|
||||||
fp: boolean;
|
fp: boolean;
|
||||||
rep: boolean;
|
rep: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
lim: number;
|
lim: number;
|
||||||
due: number;
|
due: number;
|
||||||
delay: number;
|
delay: number;
|
||||||
pausable: boolean;
|
pausable: boolean;
|
||||||
cfg: QuizConfig;
|
cfg: QuizConfig;
|
||||||
};
|
};
|
||||||
cnt: number;
|
cnt: number;
|
||||||
recentlyCompleted: boolean;
|
recentlyCompleted: boolean;
|
||||||
show_badge: boolean;
|
show_badge: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface QuizConfig {
|
export interface QuizConfig {
|
||||||
spec: undefined | true,
|
spec: undefined | true;
|
||||||
type: QuizType;
|
type: QuizType;
|
||||||
noStartPage: boolean;
|
noStartPage: boolean;
|
||||||
startpageType: QuizStartpageType;
|
startpageType: QuizStartpageType;
|
||||||
score?: boolean;
|
score?: boolean;
|
||||||
results: QuizResultsType;
|
results: QuizResultsType;
|
||||||
haveRoot: string | null;
|
haveRoot: string | null;
|
||||||
theme: QuizTheme;
|
theme: QuizTheme;
|
||||||
resultInfo: {
|
design: boolean;
|
||||||
when: "email" | "";
|
resultInfo: {
|
||||||
share: boolean;
|
when: "email" | "";
|
||||||
replay: boolean;
|
share: boolean;
|
||||||
theme: string;
|
replay: boolean;
|
||||||
reply: string;
|
theme: string;
|
||||||
replname: string;
|
reply: string;
|
||||||
showResultForm: "before" | "after";
|
replname: string;
|
||||||
|
showResultForm: "before" | "after";
|
||||||
|
};
|
||||||
|
startpage: {
|
||||||
|
description: string;
|
||||||
|
button: string;
|
||||||
|
position: QuizStartpageAlignType;
|
||||||
|
favIcon: string | null;
|
||||||
|
logo: string | null;
|
||||||
|
originalLogo: string | null;
|
||||||
|
background: {
|
||||||
|
type: null | "image" | "video";
|
||||||
|
desktop: string | null;
|
||||||
|
originalDesktop: string | null;
|
||||||
|
mobile: string | null;
|
||||||
|
originalMobile: string | null;
|
||||||
|
video: string | null;
|
||||||
|
cycle: boolean;
|
||||||
};
|
};
|
||||||
startpage: {
|
};
|
||||||
description: string;
|
formContact: {
|
||||||
button: string;
|
title: string;
|
||||||
position: QuizStartpageAlignType;
|
desc: string;
|
||||||
favIcon: string | null;
|
fields: Record<FormContactFieldName, FormContactFieldData>;
|
||||||
logo: string | null;
|
button: string;
|
||||||
originalLogo: string | null;
|
};
|
||||||
background: {
|
info: {
|
||||||
type: null | "image" | "video";
|
phonenumber: string;
|
||||||
desktop: string | null;
|
clickable: boolean;
|
||||||
originalDesktop: string | null;
|
orgname: string;
|
||||||
mobile: string | null;
|
site: string;
|
||||||
originalMobile: string | null;
|
law?: string;
|
||||||
video: string | null;
|
};
|
||||||
cycle: boolean;
|
meta: string;
|
||||||
};
|
|
||||||
};
|
|
||||||
formContact: {
|
|
||||||
title: string;
|
|
||||||
desc: string;
|
|
||||||
fields: Record<FormContactFieldName, FormContactFieldData>;
|
|
||||||
button: string;
|
|
||||||
};
|
|
||||||
info: {
|
|
||||||
phonenumber: string;
|
|
||||||
clickable: boolean;
|
|
||||||
orgname: string;
|
|
||||||
site: string;
|
|
||||||
law?: string;
|
|
||||||
};
|
|
||||||
meta: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FormContactFieldName =
|
export type FormContactFieldName =
|
||||||
| "name"
|
| "name"
|
||||||
| "email"
|
| "email"
|
||||||
| "phone"
|
| "phone"
|
||||||
| "text"
|
| "text"
|
||||||
| "address";
|
| "address";
|
||||||
|
|
||||||
type FormContactFieldData = {
|
type FormContactFieldData = {
|
||||||
text: string;
|
text: string;
|
||||||
innerText: string;
|
innerText: string;
|
||||||
key: string;
|
key: string;
|
||||||
required: boolean;
|
required: boolean;
|
||||||
used: boolean;
|
used: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface QuizItems {
|
export interface QuizItems {
|
||||||
description: string;
|
description: string;
|
||||||
id: number;
|
id: number;
|
||||||
page: number;
|
page: number;
|
||||||
required: boolean;
|
required: boolean;
|
||||||
title: string;
|
title: string;
|
||||||
type: string;
|
type: string;
|
||||||
content: unknown;
|
content: unknown;
|
||||||
}
|
}
|
||||||
|
|||||||
37
lib/ui_kit/Stepper.tsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { useTheme } from "@mui/material";
|
||||||
|
import MobileStepper from "@mui/material/MobileStepper";
|
||||||
|
import { hexToRgba } from "@utils/hexToRgba";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
activeStep: number;
|
||||||
|
steps: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ProgressMobileStepper({ activeStep, steps }: Props) {
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MobileStepper
|
||||||
|
variant="progress"
|
||||||
|
steps={steps + 1}
|
||||||
|
position="static"
|
||||||
|
activeStep={activeStep}
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
padding: "10px 0 0",
|
||||||
|
background: "transparent",
|
||||||
|
"& .MuiLinearProgress-root": {
|
||||||
|
height: "4px",
|
||||||
|
background: theme.palette.primary.light,
|
||||||
|
width: "100%",
|
||||||
|
},
|
||||||
|
"& .MuiLinearProgress-bar": { background: theme.palette.primary.main },
|
||||||
|
"& .MuiMobileStepper-progress": {
|
||||||
|
background: hexToRgba(theme.palette.primary.main, 0.5),
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
nextButton={<></>}
|
||||||
|
backButton={<></>}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
7
lib/utils/hexToRgba.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import hexRgb from "hex-rgb";
|
||||||
|
|
||||||
|
export const hexToRgba = (hexColor: string, opacity?: number): string => {
|
||||||
|
const { red, green, blue, alpha } = hexRgb(hexColor);
|
||||||
|
|
||||||
|
return `rgba(${red}, ${green}, ${blue}, ${opacity || alpha})`;
|
||||||
|
};
|
||||||
@ -1,229 +1,431 @@
|
|||||||
import { QuizTheme } from "@model/settingsData";
|
import { createTheme } from "@mui/material";
|
||||||
import { Theme, createTheme } from "@mui/material";
|
|
||||||
import themePublic from "./genericPublication";
|
import themePublic from "./genericPublication";
|
||||||
|
|
||||||
|
import type { Theme } from "@mui/material";
|
||||||
|
import type { QuizTheme } from "@model/settingsData";
|
||||||
|
|
||||||
const StandardTheme = createTheme({
|
const StandardTheme = createTheme({
|
||||||
...themePublic,
|
...themePublic,
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: "#7E2AEA",
|
main: "#7E2AEA",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#252734"
|
main: "#252734",
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: "#333647",
|
primary: "#333647",
|
||||||
secondary: "#7E2AEA",
|
secondary: "#7E2AEA",
|
||||||
},
|
},
|
||||||
|
|
||||||
background: {
|
background: {
|
||||||
default: "#FFFFFF",
|
default: "#FFFFFF",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
const StandardDarkTheme = createTheme({
|
const StandardDarkTheme = createTheme({
|
||||||
...themePublic,
|
...themePublic,
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: "#7E2AEA",
|
main: "#7E2AEA",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#252734"
|
main: "#252734",
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: "#FFFFFF",
|
primary: "#FFFFFF",
|
||||||
secondary: "#7E2AEA",
|
secondary: "#7E2AEA",
|
||||||
},
|
},
|
||||||
|
|
||||||
background: {
|
background: {
|
||||||
default: "#333647",
|
default: "#333647",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
const PinkTheme = createTheme({
|
const PinkTheme = createTheme({
|
||||||
...themePublic,
|
...themePublic,
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: "#D34085",
|
main: "#D34085",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#252734"
|
main: "#252734",
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: "#333647",
|
primary: "#333647",
|
||||||
secondary: "#D34085",
|
secondary: "#D34085",
|
||||||
},
|
},
|
||||||
|
|
||||||
background: {
|
background: {
|
||||||
default: "#FFF9FC",
|
default: "#FFF9FC",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
const PinkDarkTheme = createTheme({
|
const PinkDarkTheme = createTheme({
|
||||||
...themePublic,
|
...themePublic,
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: "#D34085",
|
main: "#D34085",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#252734"
|
main: "#252734",
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: "#FFFFFF",
|
primary: "#FFFFFF",
|
||||||
secondary: "#D34085",
|
secondary: "#D34085",
|
||||||
},
|
},
|
||||||
|
|
||||||
background: {
|
background: {
|
||||||
default: "#333647",
|
default: "#333647",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
const BlackWhiteTheme = createTheme({
|
const BlackWhiteTheme = createTheme({
|
||||||
...themePublic,
|
...themePublic,
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: "#4E4D51",
|
main: "#4E4D51",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#252734"
|
main: "#252734",
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: "#333647",
|
primary: "#333647",
|
||||||
secondary: "#FFF9FC",
|
secondary: "#FFF9FC",
|
||||||
},
|
},
|
||||||
|
|
||||||
background: {
|
background: {
|
||||||
default: "#FFFFFF",
|
default: "#FFFFFF",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
const OliveTheme = createTheme({
|
const OliveTheme = createTheme({
|
||||||
...themePublic,
|
...themePublic,
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: "#758E4F",
|
main: "#758E4F",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#252734"
|
main: "#252734",
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: "#333647",
|
primary: "#333647",
|
||||||
secondary: "#758E4F",
|
secondary: "#758E4F",
|
||||||
},
|
},
|
||||||
|
|
||||||
background: {
|
background: {
|
||||||
default: "#F9FBF1",
|
default: "#F9FBF1",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
const PurpleTheme = createTheme({
|
const PurpleTheme = createTheme({
|
||||||
...themePublic,
|
...themePublic,
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: "#7E2AEA",
|
main: "#7E2AEA",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#252734"
|
main: "#252734",
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: "#333647",
|
primary: "#333647",
|
||||||
secondary: "#7E2AEA",
|
secondary: "#7E2AEA",
|
||||||
},
|
},
|
||||||
|
|
||||||
background: {
|
background: {
|
||||||
default: "#FBF8FF",
|
default: "#FBF8FF",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
const YellowTheme = createTheme({
|
const YellowTheme = createTheme({
|
||||||
...themePublic,
|
...themePublic,
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: "#F2B133",
|
main: "#F2B133",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#252734"
|
main: "#252734",
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: "#333647",
|
primary: "#333647",
|
||||||
secondary: "#F2B133",
|
secondary: "#F2B133",
|
||||||
},
|
},
|
||||||
|
|
||||||
background: {
|
background: {
|
||||||
default: "#FFFCF6",
|
default: "#FFFCF6",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
const GoldDarkTheme = createTheme({
|
const GoldDarkTheme = createTheme({
|
||||||
...themePublic,
|
...themePublic,
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: "#E6AA37",
|
main: "#E6AA37",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#FFFCF6",
|
main: "#FFFCF6",
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: "#FFFFFF",
|
primary: "#FFFFFF",
|
||||||
secondary: "#F2B133",
|
secondary: "#F2B133",
|
||||||
},
|
},
|
||||||
|
|
||||||
background: {
|
background: {
|
||||||
default: "#333647",
|
default: "#333647",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
const BlueTheme = createTheme({
|
const BlueTheme = createTheme({
|
||||||
...themePublic,
|
...themePublic,
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: "#4964ED",
|
main: "#4964ED",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#252734"
|
main: "#252734",
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: "#333647",
|
primary: "#333647",
|
||||||
secondary: "#4964ED",
|
secondary: "#4964ED",
|
||||||
},
|
},
|
||||||
|
|
||||||
background: {
|
background: {
|
||||||
default: "#F5F7FF",
|
default: "#F5F7FF",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
const BlueDarkTheme = createTheme({
|
const BlueDarkTheme = createTheme({
|
||||||
...themePublic,
|
...themePublic,
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: "#07A0C3",
|
main: "#07A0C3",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#252734"
|
main: "#252734",
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: "#FFFFFF",
|
primary: "#FFFFFF",
|
||||||
secondary: "#07A0C3",
|
secondary: "#07A0C3",
|
||||||
},
|
},
|
||||||
|
|
||||||
background: {
|
background: {
|
||||||
default: "#333647",
|
default: "#333647",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
export const quizThemes: Record<QuizTheme, { theme: Theme; isLight: boolean; }> = {
|
const Design1 = createTheme({
|
||||||
|
...themePublic,
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
main: "#F2B133",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#252734",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: "#FFFFFF",
|
||||||
|
secondary: "#F2B133",
|
||||||
|
},
|
||||||
|
|
||||||
|
background: {
|
||||||
|
default: "#333647",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const Design2 = createTheme({
|
||||||
|
...themePublic,
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
main: "#3D9A63",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#252734",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: "#FFFFFF",
|
||||||
|
secondary: "#3D9A63",
|
||||||
|
},
|
||||||
|
|
||||||
|
background: {
|
||||||
|
default: "#333647",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const Design3 = createTheme({
|
||||||
|
...themePublic,
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
main: "#4B6A99",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#252734",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: "#252734",
|
||||||
|
secondary: "#4B6A99",
|
||||||
|
},
|
||||||
|
|
||||||
|
background: {
|
||||||
|
default: "#F5F7FF",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const Design4 = createTheme({
|
||||||
|
...themePublic,
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
main: "#FF9431",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#252734",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: "#FFFFFF",
|
||||||
|
secondary: "#FF9431",
|
||||||
|
},
|
||||||
|
|
||||||
|
background: {
|
||||||
|
default: "#333647",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const Design5 = createTheme({
|
||||||
|
...themePublic,
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
main: "#2D99BA",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#252734",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: "#FFFFFF",
|
||||||
|
secondary: "#2D99BA",
|
||||||
|
},
|
||||||
|
|
||||||
|
background: {
|
||||||
|
default: "#333647",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const Design6 = createTheme({
|
||||||
|
...themePublic,
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
main: "#D34085",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#252734",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: "#FFFFFF",
|
||||||
|
secondary: "#D34085",
|
||||||
|
},
|
||||||
|
|
||||||
|
background: {
|
||||||
|
default: "#333647",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const Design7 = createTheme({
|
||||||
|
...themePublic,
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
main: "#B47C3B",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#252734",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: "#FFFFFF",
|
||||||
|
secondary: "#B47C3B",
|
||||||
|
},
|
||||||
|
|
||||||
|
background: {
|
||||||
|
default: "#333647",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const Design8 = createTheme({
|
||||||
|
...themePublic,
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
main: "#F0B136",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#252734",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: "#FFFFFF",
|
||||||
|
secondary: "#F0B136",
|
||||||
|
},
|
||||||
|
|
||||||
|
background: {
|
||||||
|
default: "#333647",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const Design9 = createTheme({
|
||||||
|
...themePublic,
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
main: "#678F48",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#252734",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: "#FFFFFF",
|
||||||
|
secondary: "#678F48",
|
||||||
|
},
|
||||||
|
|
||||||
|
background: {
|
||||||
|
default: "#333647",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const Design10 = createTheme({
|
||||||
|
...themePublic,
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
main: "#3666AF",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#252734",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: "#FFFFFF",
|
||||||
|
secondary: "#3666AF",
|
||||||
|
},
|
||||||
|
|
||||||
|
background: {
|
||||||
|
default: "#333647",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const quizThemes: Record<QuizTheme, { theme: Theme; isLight: boolean }> =
|
||||||
|
{
|
||||||
StandardTheme: { theme: StandardTheme, isLight: true },
|
StandardTheme: { theme: StandardTheme, isLight: true },
|
||||||
StandardDarkTheme: { theme: StandardDarkTheme, isLight: false },
|
StandardDarkTheme: { theme: StandardDarkTheme, isLight: false },
|
||||||
PinkTheme: { theme: PinkTheme, isLight: true },
|
PinkTheme: { theme: PinkTheme, isLight: true },
|
||||||
@ -235,4 +437,14 @@ export const quizThemes: Record<QuizTheme, { theme: Theme; isLight: boolean; }>
|
|||||||
PurpleTheme: { theme: PurpleTheme, isLight: true },
|
PurpleTheme: { theme: PurpleTheme, isLight: true },
|
||||||
BlueTheme: { theme: BlueTheme, isLight: true },
|
BlueTheme: { theme: BlueTheme, isLight: true },
|
||||||
BlueDarkTheme: { theme: BlueDarkTheme, isLight: false },
|
BlueDarkTheme: { theme: BlueDarkTheme, isLight: false },
|
||||||
};
|
Design1: { theme: Design1, isLight: false },
|
||||||
|
Design2: { theme: Design2, isLight: false },
|
||||||
|
Design3: { theme: Design3, isLight: true },
|
||||||
|
Design4: { theme: Design4, isLight: false },
|
||||||
|
Design5: { theme: Design5, isLight: false },
|
||||||
|
Design6: { theme: Design6, isLight: false },
|
||||||
|
Design7: { theme: Design7, isLight: false },
|
||||||
|
Design8: { theme: Design8, isLight: false },
|
||||||
|
Design9: { theme: Design9, isLight: false },
|
||||||
|
Design10: { theme: Design10, isLight: false },
|
||||||
|
};
|
||||||
|
|||||||
@ -85,6 +85,7 @@
|
|||||||
"zustand": "^4.3.8"
|
"zustand": "^4.3.8"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"country-flag-emoji-polyfill": "^0.1.8"
|
"country-flag-emoji-polyfill": "^0.1.8",
|
||||||
|
"hex-rgb": "^5.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
47
src/App.tsx
@ -7,32 +7,33 @@ import QuizAnswerer from "../lib/components/QuizAnswerer";
|
|||||||
import { ApologyPage } from "../lib/components/ViewPublicationPage/ApologyPage";
|
import { ApologyPage } from "../lib/components/ViewPublicationPage/ApologyPage";
|
||||||
|
|
||||||
// const defaultQuizId = "45ef7f9c-784d-4e58-badb-f6b337f08ba0"; // branching
|
// const defaultQuizId = "45ef7f9c-784d-4e58-badb-f6b337f08ba0"; // branching
|
||||||
const defaultQuizId = "cde381db-8ccb-402c-b55f-2c814be9bf25"; //looooong header
|
const defaultQuizId = "eb1a0fd5-8484-4c96-8d73-4af747eaf02d"; //looooong header
|
||||||
// const defaultQuizId = "ad7f5a87-b833-4f5b-854e-453706ed655c"; // linear
|
// const defaultQuizId = "ad7f5a87-b833-4f5b-854e-453706ed655c"; // linear
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const quizId = useParams().quizId ?? defaultQuizId;
|
const quizId = useParams().quizId ?? defaultQuizId;
|
||||||
const { data, error, isLoading } = useSWR(["quizData", quizId], params => getQuizData(params[1]), {
|
const { data, error, isLoading } = useSWR(
|
||||||
revalidateOnFocus: false,
|
["quizData", quizId],
|
||||||
revalidateOnReconnect: false,
|
(params) => getQuizData(params[1]),
|
||||||
shouldRetryOnError: false,
|
{
|
||||||
refreshInterval: 0,
|
revalidateOnFocus: false,
|
||||||
});
|
revalidateOnReconnect: false,
|
||||||
|
shouldRetryOnError: false,
|
||||||
|
refreshInterval: 0,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (isLoading) return <LoadingSkeleton />;
|
if (isLoading) return <LoadingSkeleton />;
|
||||||
if (error) return <ApologyPage error={error} />;
|
if (error) return <ApologyPage error={error} />;
|
||||||
if (!data) throw new Error("Quiz data is null");
|
if (!data) throw new Error("Quiz data is null");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{
|
<Box
|
||||||
// height: "100dvh",
|
sx={{
|
||||||
height: "600px",
|
height: "100dvh",
|
||||||
width: "600px",
|
}}
|
||||||
}}>
|
>
|
||||||
<QuizAnswerer
|
<QuizAnswerer quizSettings={data} quizId={quizId} />
|
||||||
quizSettings={data}
|
</Box>
|
||||||
quizId={quizId}
|
);
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,9 @@
|
|||||||
"strict": true,
|
"strict": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"./lib/*"
|
||||||
|
],
|
||||||
"@ui_kit/*": [
|
"@ui_kit/*": [
|
||||||
"./lib/ui_kit/*"
|
"./lib/ui_kit/*"
|
||||||
],
|
],
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { resolve } from "path";
|
|||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
|
|
||||||
export const alias = {
|
export const alias = {
|
||||||
|
"@": resolve(__dirname, "./lib/"),
|
||||||
"@ui_kit": resolve(__dirname, "./lib/ui_kit"),
|
"@ui_kit": resolve(__dirname, "./lib/ui_kit"),
|
||||||
"@icons": resolve(__dirname, "./lib/assets/icons"),
|
"@icons": resolve(__dirname, "./lib/assets/icons"),
|
||||||
"@stores": resolve(__dirname, "./lib/stores"),
|
"@stores": resolve(__dirname, "./lib/stores"),
|
||||||
|
|||||||
@ -2269,6 +2269,11 @@ he@^1.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||||
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
||||||
|
|
||||||
|
hex-rgb@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/hex-rgb/-/hex-rgb-5.0.0.tgz#e2c9eb6a37498d66c5a350a221ed4c2c7d1a92d6"
|
||||||
|
integrity sha512-NQO+lgVUCtHxZ792FodgW0zflK+ozS9X9dwGp9XvvmPlH7pyxd588cn24TD3rmPm/N0AIRXF10Otah8yKqGw4w==
|
||||||
|
|
||||||
hoist-non-react-statics@^3.3.1:
|
hoist-non-react-statics@^3.3.1:
|
||||||
version "3.3.2"
|
version "3.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||||
|
|||||||