Merge branch 'dev' into 'staging'

Dev

See merge request frontend/squzanswerer!176
This commit is contained in:
Nastya 2024-10-26 17:25:54 +00:00
commit c8d157e9c4
12 changed files with 227 additions and 91 deletions

@ -252,3 +252,40 @@ export function sendFC({ questionId, body, qid, preview }: SendFCParams) {
method: "POST",
});
}
//форма контактов
export type SendResultParams = {
questionId: string;
pointsSum: number;
qid: string;
preview: boolean;
};
export function sendResult({ questionId, pointsSum, qid, preview }: SendResultParams) {
if (preview) return;
const formData = new FormData();
// const keysBody = Object.keys(body)
// const content:any = {}
// fields.forEach((key) => {
// if (keysBody.includes(key)) content[key] = body.key
// })
const answers = [
{
question_id: questionId,
content: pointsSum.toString(),
result: false,
qid,
},
];
formData.append("answers", JSON.stringify(answers));
formData.append("qid", qid);
return publicationMakeRequest({
url: domain + `/answer/v1.0.0/answer`,
body: formData,
method: "POST",
});
}

@ -20,9 +20,13 @@ import { ApologyPage } from "./ViewPublicationPage/ApologyPage";
import ViewPublicationPage from "./ViewPublicationPage/ViewPublicationPage";
import { HelmetProvider } from "react-helmet-async";
import "moment/dist/locale/ru";
moment.locale("ru");
const localeText = ruRU.components.MuiLocalizationProvider.defaultProps.localeText;
console.log(localeText);
console.log(moment);
type Props = {
quizSettings?: QuizSettings;
quizId: string;

@ -24,11 +24,14 @@ 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;
onShowResult: () => void;
};
//Костыль для особого квиза. Для него не нужно показывать email адрес
const isDisableEmail = window.location.pathname.includes("/377c7570-1bee-4320-ac1e-d731b6223ce8");
export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
const theme = useTheme();
@ -114,7 +117,8 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
async function handleShowResultsClick() {
const FC = settings.cfg.formContact.fields;
if (FC["email"].used !== EMAIL_REGEXP.test(email)) {
if (!isDisableEmail && FC["email"].used !== EMAIL_REGEXP.test(email)) {
return enqueueSnackbar("введена некорректная почта");
}
@ -250,6 +254,9 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
setText={setText}
adress={adress}
setAdress={setAdress}
crutch={{
disableEmail: isDisableEmail,
}}
/>
</Box>
<Box
@ -315,9 +322,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/answer/v1.0.0/logo?q=${quizId}`}
sx={{
display: "flex",
alignItems: "center",

@ -19,6 +19,9 @@ type InputsProps = {
setText: Dispatch<SetStateAction<string>>;
adress: string;
setAdress: Dispatch<SetStateAction<string>>;
crutch: {
disableEmail: boolean;
};
};
export const Inputs = ({
@ -32,6 +35,7 @@ export const Inputs = ({
setText,
adress,
setAdress,
crutch,
}: InputsProps) => {
const { settings } = useQuizSettings();
const FC = settings.cfg.formContact.fields;
@ -95,7 +99,7 @@ export const Inputs = ({
return (
<>
{FC["name"].used ? Name : <></>}
{FC["email"].used ? Email : <></>}
{FC["email"].used && !crutch.disableEmail ? Email : <></>}
{FC["phone"].used ? Phone : <></>}
{FC["text"].used ? Text : <></>}
{FC["address"].used ? Adress : <></>}

@ -7,7 +7,6 @@ import { AnyTypedQuizQuestion, QuizQuestionVariant } from "@/index";
export const PointSystemResultList = () => {
const theme = useTheme();
const { questions } = useQuizSettings();
const answers = useQuizViewStore((state) => state.answers);
@ -20,7 +19,6 @@ export const PointSystemResultList = () => {
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;
@ -55,14 +53,20 @@ export const PointSystemResultList = () => {
>
{currentQuestion.page + 1}.
</Typography>
<Typography>{currentQuestion.title || "Вопрос без названия"}</Typography>
<Typography
sx={{
color: theme.palette.text.primary,
}}
>
{currentQuestion.title || "Вопрос без названия"}
</Typography>
</Box>
<Typography
sx={{
color: answeredVariant?.points ? "inherit" : theme.palette.grey[500],
color: answeredVariant?.points ? theme.palette.primary.main : theme.palette.grey[500],
}}
>
{answeredVariant?.points || "0"}/1
{answeredVariant?.points || "0"}
</Typography>
</Box>
<Box

@ -22,7 +22,8 @@ import { notReachable } from "@utils/notReachable";
import { quizThemes } from "@utils/themes/Publication/themePublication";
import { DESIGN_LIST } from "@/utils/designList";
import type { ReactNode } from "react";
import { type ReactNode } from "react";
import { isProduction } from "@/utils/defineDomain";
type Props = {
currentQuestion: RealTypedQuizQuestion;
@ -95,7 +96,7 @@ export const Question = ({
{show_badge && (
<Link
target="_blank"
href={`https://${window.location.hostname.includes("s") ? "s" : ""}quiz.pena.digital/answer/v1.0.0/logo?q=${quizId}`}
href={`https://${isProduction ? "" : "s"}quiz.pena.digital/answer/v1.0.0/logo?q=${quizId}`}
sx={{
mt: "20px",
alignSelf: "end",
@ -123,7 +124,11 @@ export const Question = ({
</Box>
</Box>
{questionSelect}
<Footer stepNumber={currentQuestionStepNumber} prevButton={prevButton} nextButton={nextButton} />
<Footer
stepNumber={currentQuestionStepNumber}
prevButton={prevButton}
nextButton={nextButton}
/>
</Box>
</Box>
);
@ -140,7 +145,12 @@ function QuestionByType({ question, stepNumber }: { question: RealTypedQuizQuest
case "emoji":
return <Emoji currentQuestion={question} />;
case "text":
return <Text currentQuestion={question} stepNumber={stepNumber} />;
return (
<Text
currentQuestion={question}
stepNumber={stepNumber}
/>
);
case "select":
return <Select currentQuestion={question} />;
case "date":

@ -16,6 +16,9 @@ import type { QuizQuestionResult } from "@/model/questionTypes/result";
import QuizVideo from "@/ui_kit/VideoIframe/VideoIframe";
import { TextAccordion } from "./tools/TextAccordion";
import { PointSystemResultList } from "./PointSystemResultList";
import { enqueueSnackbar } from "notistack";
import { sendFC, sendResult } from "@/api/quizRelase";
import { isProduction } from "@/utils/defineDomain";
type ResultFormProps = {
resultQuestion: QuizQuestionResult;
@ -25,8 +28,10 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
const theme = useTheme();
const isMobile = useRootContainerSize() < 650;
const isTablet = useRootContainerSize() < 1000;
const { settings, show_badge, quizId } = useQuizSettings();
const { settings, show_badge, quizId, questions, preview } = useQuizSettings();
const setCurrentQuizStep = useQuizViewStore((state) => state.setCurrentQuizStep);
//Список засчитанных баллов для балловых квизов
const pointsSum = useQuizViewStore((state) => state.pointsSum);
const spec = settings.cfg.spec;
const vkMetrics = useVkMetricsGoals(settings.cfg.vkMetricsNumber);
const yandexMetrics = useYandexMetricsGoals(settings.cfg.yandexMetricsNumber);
@ -36,6 +41,41 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
yandexMetrics.resultIdShown(resultQuestion.id);
}, [resultQuestion.id, vkMetrics, yandexMetrics]);
useEffect(() => {
(async () => {
if (!settings.cfg.showfc) {
try {
await sendFC({
questionId: resultQuestion.id,
body: {},
qid: quizId,
preview,
});
const sessions = JSON.parse(localStorage.getItem("sessions") || "{}");
localStorage.setItem("sessions", JSON.stringify({ ...sessions, [quizId]: new Date().getTime() }));
} catch (e) {
enqueueSnackbar("Заявка не может быть отправлена");
}
}
if (Boolean(settings.cfg.score)) {
try {
await sendResult({
questionId: resultQuestion.id,
pointsSum,
qid: quizId,
preview,
});
const sessions = JSON.parse(localStorage.getItem("sessions") || "{}");
localStorage.setItem("sessions", JSON.stringify({ ...sessions, [quizId]: new Date().getTime() }));
} catch (e) {
enqueueSnackbar("Количество баллов не может быть отправлено");
}
}
})();
}, []);
return (
<Box
sx={{
@ -188,32 +228,53 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
</Typography>
)}
{settings.cfg?.score && (
<TextAccordion
headerText={
<Typography
sx={{
color: theme.palette.primary.main,
"&:hover": {
color: theme.palette.primary.dark,
},
}}
>
Посмотреть ответы
</Typography>
}
sx={{
mt: "60px",
width: "100%",
}}
>
<Box
<>
<Typography
sx={{
mt: "25px",
color: theme.palette.primary.main,
fontSize: "30px",
m: "30px 0",
fontWeight: 600,
}}
>
<PointSystemResultList />
</Box>
</TextAccordion>
Ваши баллы
</Typography>
<Typography
sx={{
color: theme.palette.primary.main,
fontSize: "30px",
fontWeight: 600,
}}
>
{pointsSum} из {questions.filter((e) => e.type != "result").length}
</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>
@ -221,9 +282,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
<Box
component={Link}
target={"_blank"}
href={`https://${
window.location.hostname.includes("s") ? "s" : ""
}quiz.pena.digital/answer/v1.0.0/logo?q=${quizId}`}
href={`https://${isProduction ? "" : "s"}quiz.pena.digital/answer/v1.0.0/logo?q=${quizId}`}
sx={{
display: "flex",
alignItems: "center",

@ -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/answer/v1.0.0/logo?q=${quizId}`}
sx={{
display: "flex",
alignItems: "center",

@ -5,13 +5,13 @@ import { DateCalendar } from "@mui/x-date-pickers";
import { quizThemes } from "@utils/themes/Publication/themePublication";
import type { Moment } from "moment";
import moment from "moment";
import { Paper, useTheme } from "@mui/material";
import { Box, Paper, TextField, useTheme } from "@mui/material";
import { useRootContainerSize } from "@/contexts/RootContainerWidthContext";
type DateProps = {
currentQuestion: QuizQuestionDate;
};
console.log(moment.locale());
export default ({ currentQuestion }: DateProps) => {
const theme = useTheme();
const isMobile = useRootContainerSize() < 690;
@ -46,48 +46,55 @@ export default ({ currentQuestion }: DateProps) => {
display: "inline-flex",
flexWrap: "wrap",
marginTop: "20px",
p: "20px",
}}
>
<DateCalendar
sx={{
"& .MuiInputBase-root": {
backgroundColor: settings.cfg.design
? quizThemes[settings.cfg.theme].isLight
? "#F2F3F7"
: "rgba(154,154,175, 0.2)"
: quizThemes[settings.cfg.theme].isLight
? "white"
: theme.palette.background.default,
borderRadius: "10px",
maxWidth: "250px",
pr: "30px",
"& input": { py: "11px", pl: "20px", lineHeight: "19px" },
"& fieldset": { borderColor: "#9A9AAF" },
},
}}
value={currentFrom}
onChange={(data) => onDateChange(data, 0)}
/>
<DateCalendar
sx={{
"& .MuiInputBase-root": {
backgroundColor: settings.cfg.design
? quizThemes[settings.cfg.theme].isLight
? "#F2F3F7"
: "rgba(154,154,175, 0.2)"
: quizThemes[settings.cfg.theme].isLight
? "white"
: theme.palette.background.default,
borderRadius: "10px",
maxWidth: "250px",
pr: "30px",
"& input": { py: "11px", pl: "20px", lineHeight: "19px" },
"& fieldset": { borderColor: "#9A9AAF" },
},
}}
value={currentTo}
onChange={(data) => onDateChange(data, 1)}
/>
<Box>
<span style={{ marginLeft: "25px", color: theme.palette.text.primary }}>От</span>
<DateCalendar
sx={{
"& .MuiInputBase-root": {
backgroundColor: settings.cfg.design
? quizThemes[settings.cfg.theme].isLight
? "#F2F3F7"
: "rgba(154,154,175, 0.2)"
: quizThemes[settings.cfg.theme].isLight
? "white"
: theme.palette.background.default,
borderRadius: "10px",
maxWidth: "250px",
pr: "30px",
"& input": { py: "11px", pl: "20px", lineHeight: "19px" },
"& fieldset": { borderColor: "#9A9AAF" },
},
}}
value={currentFrom}
onChange={(data) => onDateChange(data, 0)}
/>
</Box>
<Box>
<span style={{ marginLeft: "25px", color: theme.palette.text.primary }}>До</span>
<DateCalendar
sx={{
"& .MuiInputBase-root": {
backgroundColor: settings.cfg.design
? quizThemes[settings.cfg.theme].isLight
? "#F2F3F7"
: "rgba(154,154,175, 0.2)"
: quizThemes[settings.cfg.theme].isLight
? "white"
: theme.palette.background.default,
borderRadius: "10px",
maxWidth: "250px",
pr: "30px",
"& input": { py: "11px", pl: "20px", lineHeight: "19px" },
"& fieldset": { borderColor: "#9A9AAF" },
},
}}
value={currentTo}
onChange={(data) => onDateChange(data, 1)}
/>
</Box>
</Paper>
);
};

@ -28,7 +28,7 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
{currentQuestion.title}
</Typography>
<RadioGroup
name={currentQuestion.id}
name={currentQuestion.id.toString()}
value={currentQuestion.content.variants.findIndex(({ id }) => answer === id)}
sx={{
display: "flex",

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

@ -127,6 +127,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
);
@ -136,7 +137,6 @@ export function useQuestionFlowControl() {
);
//Извлекаем самое большое число
const indexOfNext = Math.max(...numbers);
//Отдаём индекс нужного нам результата
return results[numbers.indexOf(indexOfNext)];
}, [pointsSum, sortedQuestions]);