Merge branch 'ball'

This commit is contained in:
Nastya 2024-10-23 16:24:33 +03:00
commit 44a192e8ad
10 changed files with 358 additions and 10 deletions

@ -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>
);
};

@ -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>
);
};

@ -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 { QuizQuestionResult } from "@model/questionTypes/result";
import type { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
import { isProduction } from "@/utils/defineDomain";
type Props = {
currentQuestion: AnyTypedQuizQuestion;
@ -315,9 +316,7 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
<Box
component={Link}
target={"_blank"}
href={`https://${
window.location.hostname[0] === "s" ? "s" : ""
}quiz.pena.digital/squiz/quiz/logo?q=${quizId}`}
href={`https://${isProduction ? "" : "s"}quiz.pena.digital/squiz/quiz/logo?q=${quizId}`}
sx={{
display: "flex",
alignItems: "center",

@ -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 QuizVideo from "@/ui_kit/VideoIframe/VideoIframe";
import { TextAccordion } from "./tools/TextAccordion";
import { PointSystemResultList } from "./PointSystemResultList";
type ResultFormProps = {
resultQuestion: QuizQuestionResult;
@ -185,6 +187,32 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
{resultQuestion.content.text}
</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>
{show_badge && (

@ -16,6 +16,8 @@ import { useVkMetricsGoals } from "@/utils/hooks/metrics/useVkMetricsGoals";
import { useYandexMetricsGoals } from "@/utils/hooks/metrics/useYandexMetricsGoals";
import QuizVideo from "@/ui_kit/VideoIframe/VideoIframe";
import { isProduction } from "@/utils/defineDomain";
export const StartPageViewPublication = () => {
const theme = useTheme();
const { settings, show_badge, quizId, questions } = useQuizSettings();
@ -135,8 +137,7 @@ export const StartPageViewPublication = () => {
<Box
component={Link}
target={"_blank"}
href={`https://${window.location.hostname[0] === "s" ? "s" : ""
}quiz.pena.digital/squiz/quiz/logo?q=${quizId}`}
href={`https://${isProduction ? "" : "s"}quiz.pena.digital/squiz/quiz/logo?q=${quizId}`}
sx={{
display: "flex",
alignItems: "center",

@ -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";
const currentDomain = location.hostname;
//туризм больше не в исключениях
if (currentDomain === "s.hbpn.link" || currentDomain.includes("localhost") || currentDomain.includes("127.0.0.1"))
domain = "https://s.hbpn.link";
const isProduction = !(
currentDomain === "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 results = sortedQuestions.filter(
(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);
//Отдаём индекс нужного нам результата
return results[numbers.indexOf(indexOfNext)];
}, [pointsSum, sortedQuestions]);