Merge branch 'ball'
This commit is contained in:
commit
44a192e8ad
39
lib/assets/icons/CorrectAnswer.tsx
Normal file
39
lib/assets/icons/CorrectAnswer.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { Box, SxProps } from "@mui/material";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
sx?: SxProps;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CorrectAnswer = ({ sx }: Props) => {
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
...sx,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<circle
|
||||||
|
cx="12"
|
||||||
|
cy="12"
|
||||||
|
r="10"
|
||||||
|
stroke="#0D9F00"
|
||||||
|
stroke-width="1.5"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M9.30078 11.8L11.3008 13.8L15.3008 9.79999"
|
||||||
|
stroke="#0D9F00"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
46
lib/assets/icons/IncorrectAnswer.tsx
Normal file
46
lib/assets/icons/IncorrectAnswer.tsx
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { Box, SxProps } from "@mui/material";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
sx?: SxProps;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const IncorrectAnswer = ({ sx }: Props) => {
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
...sx,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<circle
|
||||||
|
cx="12"
|
||||||
|
cy="12"
|
||||||
|
r="10"
|
||||||
|
stroke="#E02C2C"
|
||||||
|
stroke-width="1.5"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M9.87845 14.1198L14.1211 9.87714"
|
||||||
|
stroke="#E02C2C"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M9.87845 9.87668L14.1211 14.1193"
|
||||||
|
stroke="#E02C2C"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
45
lib/assets/icons/TickOpenClose.tsx
Normal file
45
lib/assets/icons/TickOpenClose.tsx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { Box, SxProps } from "@mui/material";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
checked?: boolean;
|
||||||
|
sx?: SxProps;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TickOpenClose = ({ checked = false, sx }: Props) => {
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
transform: checked ? "" : "rotate(180deg)",
|
||||||
|
transition: "transform 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms",
|
||||||
|
width: "14px",
|
||||||
|
height: "14px",
|
||||||
|
transformOrigin: "center center",
|
||||||
|
display: "flex",
|
||||||
|
...sx,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="14"
|
||||||
|
height="13"
|
||||||
|
viewBox="0 0 14 13"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M13 3.48425L7 9.48425"
|
||||||
|
stroke="#7E2AEA"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M1 3.48425L7 9.48425"
|
||||||
|
stroke="#7E2AEA"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
@ -24,6 +24,7 @@ import { NameplateLogo } from "@icons/NameplateLogo";
|
|||||||
import type { FormContactFieldData, FormContactFieldName } from "@model/settingsData";
|
import type { FormContactFieldData, FormContactFieldName } from "@model/settingsData";
|
||||||
import type { QuizQuestionResult } from "@model/questionTypes/result";
|
import type { QuizQuestionResult } from "@model/questionTypes/result";
|
||||||
import type { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
|
import type { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
|
||||||
|
import { isProduction } from "@/utils/defineDomain";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
currentQuestion: AnyTypedQuizQuestion;
|
currentQuestion: AnyTypedQuizQuestion;
|
||||||
@ -315,9 +316,7 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
|
|||||||
<Box
|
<Box
|
||||||
component={Link}
|
component={Link}
|
||||||
target={"_blank"}
|
target={"_blank"}
|
||||||
href={`https://${
|
href={`https://${isProduction ? "" : "s"}quiz.pena.digital/squiz/quiz/logo?q=${quizId}`}
|
||||||
window.location.hostname[0] === "s" ? "s" : ""
|
|
||||||
}quiz.pena.digital/squiz/quiz/logo?q=${quizId}`}
|
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
|
142
lib/components/ViewPublicationPage/PointSystemResultList.tsx
Normal file
142
lib/components/ViewPublicationPage/PointSystemResultList.tsx
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
import { IncorrectAnswer } from "@/assets/icons/IncorrectAnswer";
|
||||||
|
import { CorrectAnswer } from "@/assets/icons/CorrectAnswer";
|
||||||
|
import { Box, Typography, useTheme } from "@mui/material";
|
||||||
|
import { useQuizSettings } from "@/contexts/QuizDataContext";
|
||||||
|
import { useQuizViewStore } from "@/stores/quizView";
|
||||||
|
import { AnyTypedQuizQuestion, QuizQuestionVariant } from "@/index";
|
||||||
|
|
||||||
|
export const PointSystemResultList = () => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const { questions } = useQuizSettings();
|
||||||
|
const answers = useQuizViewStore((state) => state.answers);
|
||||||
|
|
||||||
|
const questionsWothoutResult = questions.filter<QuizQuestionVariant>(
|
||||||
|
(q: AnyTypedQuizQuestion): q is QuizQuestionVariant => q.type === "variant"
|
||||||
|
);
|
||||||
|
|
||||||
|
return questionsWothoutResult.map((currentQuestion) => {
|
||||||
|
let answerIndex = 0;
|
||||||
|
let currentVariants = currentQuestion.content.variants;
|
||||||
|
|
||||||
|
const currentAnswer = answers.find((a) => a.questionId === currentQuestion.id);
|
||||||
|
const answeredVariant = currentVariants.find((v, i) => {
|
||||||
|
if (v.id === currentAnswer?.answer) {
|
||||||
|
answerIndex = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "inline-flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "inline-flex",
|
||||||
|
gap: "16px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
color: theme.palette.grey[500],
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{currentQuestion.page + 1}.
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{currentQuestion.title || "Вопрос без названия"}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
color: answeredVariant?.points ? "inherit" : theme.palette.grey[500],
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{answeredVariant?.points || "0"}/10
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "inline-flex",
|
||||||
|
mt: "15px",
|
||||||
|
gap: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
color: theme.palette.grey[500],
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Ваш ответ:
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Line
|
||||||
|
checkTrue={Boolean(answeredVariant?.points)}
|
||||||
|
text={answeredVariant?.answer}
|
||||||
|
/>
|
||||||
|
{/* {Boolean(answeredVariant?.points) ? <CorrectAnswer /> : <IncorrectAnswer />}
|
||||||
|
<Typography>{answeredVariant?.answer || "не выбрано"}</Typography> */}
|
||||||
|
{currentVariants.map((v) => {
|
||||||
|
if (v.id === currentAnswer?.answer) {
|
||||||
|
return <></>;
|
||||||
|
} else
|
||||||
|
return (
|
||||||
|
<Line
|
||||||
|
checkTrue={Boolean(v?.points)}
|
||||||
|
text={v.answer}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
interface LineProps {
|
||||||
|
checkTrue: boolean;
|
||||||
|
text?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Line = ({ checkTrue, text }: LineProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "inline-flex",
|
||||||
|
gap: "10px",
|
||||||
|
mb: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{checkTrue ? <CorrectAnswer /> : <IncorrectAnswer />}
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
color: theme.palette.grey[500],
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{text || "не выбрано"}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
@ -14,6 +14,8 @@ import { NameplateLogo } from "@icons/NameplateLogo";
|
|||||||
|
|
||||||
import type { QuizQuestionResult } from "@/model/questionTypes/result";
|
import type { QuizQuestionResult } from "@/model/questionTypes/result";
|
||||||
import QuizVideo from "@/ui_kit/VideoIframe/VideoIframe";
|
import QuizVideo from "@/ui_kit/VideoIframe/VideoIframe";
|
||||||
|
import { TextAccordion } from "./tools/TextAccordion";
|
||||||
|
import { PointSystemResultList } from "./PointSystemResultList";
|
||||||
|
|
||||||
type ResultFormProps = {
|
type ResultFormProps = {
|
||||||
resultQuestion: QuizQuestionResult;
|
resultQuestion: QuizQuestionResult;
|
||||||
@ -185,6 +187,32 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
|
|||||||
{resultQuestion.content.text}
|
{resultQuestion.content.text}
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
|
<TextAccordion
|
||||||
|
headerText={
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
"&:hover": {
|
||||||
|
color: theme.palette.primary.dark,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Посмотреть ответы
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
sx={{
|
||||||
|
mt: "60px",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
mt: "25px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PointSystemResultList />
|
||||||
|
</Box>
|
||||||
|
</TextAccordion>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
{show_badge && (
|
{show_badge && (
|
||||||
|
@ -16,6 +16,8 @@ import { useVkMetricsGoals } from "@/utils/hooks/metrics/useVkMetricsGoals";
|
|||||||
import { useYandexMetricsGoals } from "@/utils/hooks/metrics/useYandexMetricsGoals";
|
import { useYandexMetricsGoals } from "@/utils/hooks/metrics/useYandexMetricsGoals";
|
||||||
import QuizVideo from "@/ui_kit/VideoIframe/VideoIframe";
|
import QuizVideo from "@/ui_kit/VideoIframe/VideoIframe";
|
||||||
|
|
||||||
|
import { isProduction } from "@/utils/defineDomain";
|
||||||
|
|
||||||
export const StartPageViewPublication = () => {
|
export const StartPageViewPublication = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { settings, show_badge, quizId, questions } = useQuizSettings();
|
const { settings, show_badge, quizId, questions } = useQuizSettings();
|
||||||
@ -135,8 +137,7 @@ export const StartPageViewPublication = () => {
|
|||||||
<Box
|
<Box
|
||||||
component={Link}
|
component={Link}
|
||||||
target={"_blank"}
|
target={"_blank"}
|
||||||
href={`https://${window.location.hostname[0] === "s" ? "s" : ""
|
href={`https://${isProduction ? "" : "s"}quiz.pena.digital/squiz/quiz/logo?q=${quizId}`}
|
||||||
}quiz.pena.digital/squiz/quiz/logo?q=${quizId}`}
|
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
|
43
lib/components/ViewPublicationPage/tools/TextAccordion.tsx
Normal file
43
lib/components/ViewPublicationPage/tools/TextAccordion.tsx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { TickOpenClose } from "@/assets/icons/TickOpenClose";
|
||||||
|
import { Box, SxProps, Typography, useTheme } from "@mui/material";
|
||||||
|
import { useState, ReactNode } from "react";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
headerText: ReactNode;
|
||||||
|
children: ReactNode;
|
||||||
|
sx?: SxProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TextAccordion = ({ headerText, children, sx }: Props) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={sx}
|
||||||
|
onClick={() => setOpen((old) => !old)}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
userSelect: "none",
|
||||||
|
display: "flex",
|
||||||
|
gap: "10px",
|
||||||
|
cursor: "pointer",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{headerText}
|
||||||
|
<TickOpenClose
|
||||||
|
checked={open}
|
||||||
|
sx={{
|
||||||
|
"&:hover": {
|
||||||
|
color: theme.palette.primary.dark,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
{open && children}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
@ -5,8 +5,13 @@
|
|||||||
let domain = "https://hbpn.link";
|
let domain = "https://hbpn.link";
|
||||||
const currentDomain = location.hostname;
|
const currentDomain = location.hostname;
|
||||||
|
|
||||||
//туризм больше не в исключениях
|
const isProduction = !(
|
||||||
if (currentDomain === "s.hbpn.link" || currentDomain.includes("localhost") || currentDomain.includes("127.0.0.1"))
|
currentDomain === "s.hbpn.link" ||
|
||||||
domain = "https://s.hbpn.link";
|
currentDomain.includes("localhost") ||
|
||||||
|
currentDomain.includes("127.0.0.1")
|
||||||
|
);
|
||||||
|
|
||||||
export { domain };
|
//туризм больше не в исключениях
|
||||||
|
if (!isProduction) domain = "https://s.hbpn.link";
|
||||||
|
|
||||||
|
export { domain, isProduction };
|
||||||
|
@ -125,6 +125,7 @@ export function useQuestionFlowControl() {
|
|||||||
//Анализ результата по количеству баллов
|
//Анализ результата по количеству баллов
|
||||||
const findResultPointsLogic = useCallback(() => {
|
const findResultPointsLogic = useCallback(() => {
|
||||||
//Отбираем из массива только тип резулт И результы с информацией о ожидаемых баллах И те результы, чьи суммы баллов меньше или равны насчитанным баллам юзера
|
//Отбираем из массива только тип резулт И результы с информацией о ожидаемых баллах И те результы, чьи суммы баллов меньше или равны насчитанным баллам юзера
|
||||||
|
|
||||||
const results = sortedQuestions.filter(
|
const results = sortedQuestions.filter(
|
||||||
(e) => e.type === "result" && e.content.rule.minScore !== undefined && e.content.rule.minScore <= pointsSum
|
(e) => e.type === "result" && e.content.rule.minScore !== undefined && e.content.rule.minScore <= pointsSum
|
||||||
);
|
);
|
||||||
@ -134,7 +135,6 @@ export function useQuestionFlowControl() {
|
|||||||
);
|
);
|
||||||
//Извлекаем самое большое число
|
//Извлекаем самое большое число
|
||||||
const indexOfNext = Math.max(...numbers);
|
const indexOfNext = Math.max(...numbers);
|
||||||
|
|
||||||
//Отдаём индекс нужного нам результата
|
//Отдаём индекс нужного нам результата
|
||||||
return results[numbers.indexOf(indexOfNext)];
|
return results[numbers.indexOf(indexOfNext)];
|
||||||
}, [pointsSum, sortedQuestions]);
|
}, [pointsSum, sortedQuestions]);
|
||||||
|
Loading…
Reference in New Issue
Block a user