frontAnswerer/lib/components/ViewPublicationPage/ContactForm/ContactForm.tsx
Nastya aefda2b767
All checks were successful
Deploy / CreateImage (push) Successful in 3m9s
Deploy / DeployService (push) Successful in 21s
Merge branch 'newai'
2025-05-02 16:02:33 +03:00

351 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useEffect, useRef, useState } from "react";
import { Box, Button, Link, Typography, useTheme } from "@mui/material";
import { enqueueSnackbar } from "notistack";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
import { Inputs } from "@/components/ViewPublicationPage/ContactForm/Inputs/Inputs";
import { ContactTextBlock } from "./ContactTextBlock";
import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
import { sendFC, SendFCParams } from "@api/quizRelase";
import { useVkMetricsGoals } from "@/utils/hooks/metrics/useVkMetricsGoals";
import { useYandexMetricsGoals } from "@/utils/hooks/metrics/useYandexMetricsGoals";
import { EMAIL_REGEXP } from "@utils/emailRegexp";
import { quizThemes } from "@utils/themes/Publication/themePublication";
import { DESIGN_LIST } from "@utils/designList";
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";
import { useQuizStore } from "@/stores/useQuizStore";
import { useTranslation } from "react-i18next";
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();
const { settings, questions, quizId, show_badge, preview } = useQuizStore();
const [ready, setReady] = useState(false);
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [phone, setPhone] = useState("");
const [text, setText] = useState("");
const [adress, setAdress] = useState("");
const [screenHeight, setScreenHeight] = useState<number>(window.innerHeight);
const fireOnce = useRef(true);
const [fire, setFire] = useState(false);
const isMobile = useRootContainerSize() < 850;
const isTablet = useRootContainerSize() < 1000;
const { t } = useTranslation();
const vkMetrics = useVkMetricsGoals(settings.cfg.vkMetricsNumber);
const yandexMetrics = useYandexMetricsGoals(settings.cfg.yandexMetricsNumber);
useEffect(() => {
function handleResize() {
setScreenHeight(window.innerHeight);
}
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
const resultQuestion =
currentQuestion.type === "result"
? currentQuestion
: questions.find((question): question is QuizQuestionResult => {
if (settings?.cfg.haveRoot) {
return question.type === "result" && question.content.rule.parentId === currentQuestion.content.id;
} else {
return question.type === "result" && question.content.rule.parentId === "line";
}
});
if (!resultQuestion) throw new Error("Result question not found");
const inputHC = async () => {
const FC = settings.cfg.formContact.fields || settings.cfg.formContact;
const body: SendFCParams["body"] = {};
if (name.length > 0) body.name = name;
if (email.length > 0) body.email = email;
if (phone.length > 0) body.phone = phone;
if (adress.length > 0) body.address = adress;
if (text.length > 0) body.customs = { [FC.text.text || t("Last name")]: text };
if (Object.keys(body).length > 0) {
try {
await sendFC({
questionId: currentQuestion.id,
body: body,
qid: quizId,
preview,
});
const sessions = JSON.parse(localStorage.getItem("sessions") || "{}");
localStorage.setItem("sessions", JSON.stringify({ ...sessions, [quizId]: new Date().getTime() }));
} catch (e) {
enqueueSnackbar(t("The answer was not counted"));
}
}
};
const FCcopy: Record<FormContactFieldName, FormContactFieldData> =
settings.cfg.formContact.fields || settings.cfg.formContact;
const filteredFC: Partial<Record<FormContactFieldName, FormContactFieldData>> = {};
for (const i in FCcopy) {
const field = FCcopy[i as keyof typeof FCcopy];
if (field.used) {
filteredFC[i as FormContactFieldName] = field;
}
}
async function handleShowResultsClick() {
const FC = settings.cfg.formContact.fields;
if (!isDisableEmail && FC["email"].used !== EMAIL_REGEXP.test(email)) {
return enqueueSnackbar("Incorrect email entered");
}
if (fireOnce.current) {
if (name.length === 0 && email.length === 0 && phone.length === 0 && text.length === 0 && adress.length === 0)
return enqueueSnackbar(t("Please fill in the fields"));
//почта валидна, хоть одно поле заполнено
setFire(true);
try {
await inputHC();
fireOnce.current = false;
const sessions = JSON.parse(localStorage.getItem("sessions") || "{}");
sessions[quizId] = Date.now();
localStorage.setItem("sessions", JSON.stringify(sessions));
vkMetrics.contactsFormFilled();
yandexMetrics.contactsFormFilled();
//Оповещаем какие поля были заполнены
if (name.length !== 0) {
vkMetrics.contactsFormField("name");
yandexMetrics.contactsFormField("name");
}
if (email.length !== 0) {
vkMetrics.contactsFormField("email");
yandexMetrics.contactsFormField("email");
}
if (phone.length !== 0) {
vkMetrics.contactsFormField("phone");
yandexMetrics.contactsFormField("phone");
}
if (text.length !== 0) {
vkMetrics.contactsFormField("text");
yandexMetrics.contactsFormField("text");
}
if (adress.length !== 0) {
vkMetrics.contactsFormField("address");
yandexMetrics.contactsFormField("address");
}
} catch (e) {
enqueueSnackbar(t("Please try again later"));
}
if (settings.cfg.resultInfo.showResultForm === "after") {
onShowResult();
}
}
setFire(false);
}
useEffect(() => {
vkMetrics.contactsFormOpened();
yandexMetrics.contactsFormOpened();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundColor: theme.palette.background.default,
height: screenHeight > 500 ? "100%" : "auto",
overflow: "auto",
"&::-webkit-scrollbar": {
width: "0",
display: "none",
msOverflowStyle: "none",
},
scrollbarWidth: "none",
msOverflowStyle: "none",
backgroundPosition: "center",
backgroundSize: "cover",
backgroundImage:
settings.cfg.design && !isMobile
? quizThemes[settings.cfg.theme].isLight
? `url(${DESIGN_LIST[settings.cfg.theme]})`
: `linear-gradient(90deg, rgba(39, 38, 38, 0.95) 7.66%, rgba(42, 42, 46, 0.85) 42.12%, rgba(51, 54, 71, 0.4) 100%), url(${
DESIGN_LIST[settings.cfg.theme]
})`
: null,
}}
>
<Box
sx={{
width: !isMobile ? "100%" : isMobile ? undefined : "530px",
borderRadius: "4px",
height: isMobile ? "100%" : "auto",
minHeight: "100%",
display: "flex",
flexDirection: isMobile ? "column" : "row",
background: settings.cfg.design && !isMobile ? undefined : theme.palette.background.default,
}}
>
<ContactTextBlock settings={settings} />
<Box
sx={{
flexGrow: isMobile ? 1 : 0,
display: "flex",
alignItems: "center",
justifyContent: "space-between",
flexDirection: "column",
backgroundColor: theme.palette.background.default,
height: "auto",
}}
>
<Box
sx={{
display: "flex",
alignItems: isMobile ? undefined : "center",
justifyContent: "center",
flexDirection: "column",
p: isMobile ? "0 20px" : isTablet ? "105px 40px 0 60px" : "105px 60px 0 60px",
margin: isMobile ? "0" : "auto 0",
}}
>
<Box
sx={{
display: "flex",
flexDirection: "column",
mt: isMobile ? "10px" : "20px",
mb: "20px",
}}
>
<Inputs
name={name}
setName={setName}
email={email}
setEmail={setEmail}
phone={phone}
setPhone={setPhone}
text={text}
setText={setText}
adress={adress}
setAdress={setAdress}
crutch={{
disableEmail: isDisableEmail,
}}
/>
</Box>
<Box
sx={{
display: "flex",
width: isMobile ? "300px" : "390px",
}}
>
<CustomCheckbox
label=""
handleChange={({ target }) => {
setReady(target.checked);
}}
checked={ready}
colorIcon={theme.palette.primary.main}
sx={{ marginRight: "0" }}
/>
<Typography
sx={{
color: theme.palette.text.primary,
lineHeight: "18.96px",
}}
fontSize={"16px"}
>
С&ensp;
<Link
href={"https://shub.pena.digital/ppdd"}
target="_blank"
>
{`${t("Regulation on the processing of personal data")} `}
</Link>
&ensp;{t("and")}&ensp;
<Link
href={"https://shub.pena.digital/docs/privacy"}
target="_blank"
>
{" "}
{`${t("Privacy Policy")} `}
</Link>
&ensp;{t("familiarized")}
</Typography>
</Box>
<Button
disabled={!(ready && !fire)}
variant="contained"
onClick={handleShowResultsClick}
sx={{
border: `1px solid ${theme.palette.primary.main}`,
margin: isMobile ? "auto" : undefined,
mt: "20px",
p: "10px 20px",
"&:disabled": {
border: "1px solid #9A9AAF",
color: "#9A9AAF",
},
}}
>
{settings.cfg.formContact?.button || t("Get results")}
</Button>
</Box>
{show_badge && (
<Box
component={Link}
target={"_blank"}
href={`https://${isProduction ? "" : "s"}quiz.pena.digital/answer/v1.0.0/logo?q=${quizId}`}
sx={{
display: "flex",
alignItems: "center",
mt: "55px",
mb: isMobile ? "30px" : isTablet ? "40px" : "50px",
gap: "10px",
textDecoration: "none",
margitTop: "auto",
}}
>
<NameplateLogo
style={{
fontSize: "20px",
color: quizThemes[settings.cfg.theme].isLight ? "#151515" : "#FFFFFF",
}}
/>
</Box>
)}
</Box>
</Box>
</Box>
);
};