frontAnswerer/src/pages/ViewPublicationPage/ContactForm.tsx
2024-01-31 15:57:07 +03:00

509 lines
18 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 AddressIcon from "@icons/ContactFormIcon/AddressIcon";
import NameIcon from "@icons/ContactFormIcon/NameIcon";
import EmailIcon from "@icons/ContactFormIcon/EmailIcon";
import PhoneIcon from "@icons/ContactFormIcon/PhoneIcon";
import TextIcon from "@icons/ContactFormIcon/TextIcon";
import { Box, Button, InputAdornment, Link, TextField as MuiTextField, TextFieldProps, Typography, useMediaQuery, useTheme } from "@mui/material";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
import { FC, useRef, useState } from "react";
import { sendFC } from "@api/quizRelase";
import { NameplateLogo } from "@icons/NameplateLogo";
import { QuizQuestionResult } from "@model/questionTypes/result";
import { quizThemes } from "@utils/themes/Publication/themePublication";
import { enqueueSnackbar } from "notistack";
import { ApologyPage } from "./ApologyPage";
import { checkEmptyData } from "./tools/checkEmptyData";
import { useQuestionsStore } from "@stores/quizData/store";
const TextField = MuiTextField as unknown as FC<TextFieldProps>; // temporary fix ts(2590)
const EMAIL_REGEXP = /^(([^<>()[\].,:\s@"]+(\.[^<>()[\].,:\s@"]+)*)|(".+"))@(([^<>()[\].,:\s@"]+\.)+[^<>()[\].,:\s@"]{2,})$/iu;
type ContactFormProps = {
currentQuestion: any;
showResultForm: boolean;
setShowContactForm: (show: boolean) => void;
setShowResultForm: (show: boolean) => void;
};
const icons = [
{
type: "name",
icon: NameIcon,
defaultText: "Введите имя",
defaultTitle: "имя",
backendName: "name",
},
{
type: "email",
icon: EmailIcon,
defaultText: "Введите Email",
defaultTitle: "Email",
backendName: "email",
},
{
type: "phone",
icon: PhoneIcon,
defaultText: "Введите номер телефона",
defaultTitle: "номер телефона",
backendName: "phone",
},
{
type: "text",
icon: TextIcon,
defaultText: "Введите фамилию",
defaultTitle: "фамилию",
backendName: "adress",
},
{
type: "address",
icon: AddressIcon,
defaultText: "Введите адрес",
defaultTitle: "адрес",
backendName: "adress",
},
];
export const ContactForm = ({
currentQuestion,
showResultForm,
setShowContactForm,
setShowResultForm,
}: ContactFormProps) => {
const theme = useTheme();
const { settings, items } = useQuestionsStore();
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 fireOnce = useRef(true);
const [fire, setFire] = useState(false);
const isMobile = useMediaQuery(theme.breakpoints.down(850));
const followNextForm = () => {
setShowContactForm(false);
setShowResultForm(true);
};
//@ts-ignore
const resultQuestion: QuizQuestionResult = items.find((question) => {
if (settings?.cfg.haveRoot) {
//ветвимся
return (
question.type === "result" &&
//@ts-ignore
question.content.rule.parentId === currentQuestion.content.id
);
} else {
// не ветвимся
return (
question.type === "result" && question.content.rule.parentId === "line"
);
}
});
const inputHC = async () => {
if (!settings) return;
//@ts-ignore
const FC = settings?.cfg.formContact.fields || settings?.cfg.formContact;
const body = {};
//@ts-ignore
if (name.length > 0) body.name = name;
//@ts-ignore
if (email.length > 0) body.email = email;
//@ts-ignore
if (phone.length > 0) body.phone = phone;
//@ts-ignore
if (adress.length > 0) body.address = adress;
//@ts-ignore
if (text.length > 0) body.customs = { [FC.text.text || "Фамилия"]: text };
if (Object.keys(body).length > 0) {
try {
await sendFC({
questionId: resultQuestion?.id,
body: body,
qid: settings.qid,
});
const sessions = JSON.parse(localStorage.getItem("sessions") || "{}");
localStorage.setItem(
"sessions",
JSON.stringify({ ...sessions, [settings.qid]: new Date().getTime() })
);
} catch (e) {
enqueueSnackbar("ответ не был засчитан");
}
}
};
//@ts-ignore
let FCcopy: any = settings?.cfg.formContact.fields || settings?.cfg.formContact;
let filteredFC: any = {};
for (let i in FCcopy) {
let field = FCcopy[i];
console.log(filteredFC);
if (field.used) {
filteredFC[i] = field;
}
}
let isWide = Object.keys(filteredFC).length > 2;
if (!settings) throw new Error("settings is null");
if (!resultQuestion)
return (
<ApologyPage message="не получилось найти результат для этой ветки :(" />
);
return (
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundColor: theme.palette.background.default,
height: "100vh",
overflow: "auto",
"&::-webkit-scrollbar": {
width: "0",
display: "none",
msOverflowStyle: "none",
},
scrollbarWidth: "none",
msOverflowStyle: "none",
}}
>
<Box
sx={{
width: isWide && !isMobile ? "100%" : isMobile ? undefined : "530px",
borderRadius: "4px",
height: "90vh",
display: isWide && !isMobile ? "flex" : undefined,
}}
>
<Box
sx={{
width: isWide && !isMobile ? "100%" : undefined,
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
borderRight: isWide && !isMobile ? "1px solid gray" : undefined,
}}
>
<Typography
sx={{
textAlign: "center",
m: "20px 0",
fontSize: "28px",
color: theme.palette.text.primary,
}}
>
{settings?.cfg.formContact.title ||
"Заполните форму, чтобы получить результаты теста"}
</Typography>
{settings?.cfg.formContact.desc && (
<Typography
sx={{
color: theme.palette.text.primary,
textAlign: "center",
m: "20px 0",
fontSize: "18px",
}}
>
{settings?.cfg.formContact.desc}
</Typography>
)}
</Box>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
flexDirection: "column",
backgroundColor: theme.palette.background.default,
p: "30px",
}}
>
<Box
sx={{
display: "flex",
flexDirection: "column",
my: "20px",
}}
>
<Inputs
name={name}
setName={setName}
email={email}
setEmail={setEmail}
phone={phone}
setPhone={setPhone}
text={text}
setText={setText}
adress={adress}
setAdress={setAdress}
/>
</Box>
{
// resultQuestion &&
// settings?.cfg.resultInfo.when === "after" &&
<Button
disabled={!(ready && !fire)}
variant="contained"
onClick={async () => {
//@ts-ignore
const FC: any = settings?.cfg.formContact.fields || settings?.cfg.formContact;
if (FC["email"].used === EMAIL_REGEXP.test(email)) {
//почта валидна
setFire(true);
if (fireOnce.current) {
if (
name.length > 0 ||
email.length > 0 ||
phone.length > 0 ||
text.length > 0 ||
adress.length > 0
) {
try {
await inputHC();
fireOnce.current = false;
const QID =
process.env.NODE_ENV === "production"
? window.location.pathname.replace(/\//g, "")
: "ef836ff8-35b1-4031-9acf-af5766bac2b2";
const sessions: any = JSON.parse(
localStorage.getItem("sessions") || "{}"
);
sessions[QID] = Date.now();
localStorage.setItem(
"sessions",
JSON.stringify(sessions)
);
enqueueSnackbar("Данные успешно отправлены");
} catch (e) {
enqueueSnackbar("повторите попытку позже");
}
if (
settings?.cfg.resultInfo.showResultForm === "after" &&
!checkEmptyData({ resultData: resultQuestion })
) {
setShowContactForm(false);
setShowResultForm(true);
}
} else {
enqueueSnackbar("Пожалуйста, заполните поля");
}
}
setFire(false);
} else {
enqueueSnackbar("введена некорректная почта");
}
}}
>
{settings?.cfg.formContact?.button || "Получить результаты"}
</Button>
}
<Box
sx={{
display: "flex",
mt: "20px",
width: isMobile ? "300px" : "450px",
}}
>
<CustomCheckbox
label=""
handleChange={({ target }) => {
setReady(target.checked);
}}
checked={ready}
colorIcon={theme.palette.primary.main}
/>
<Typography sx={{ color: theme.palette.text.primary }}>
С&ensp;
<Link href={"https://shub.pena.digital/ppdd"} target="_blank">
Положением об обработке персональных данных{" "}
</Link>
&ensp;и&ensp;
<Link
href={"https://shub.pena.digital/docs/privacy"}
target="_blank"
>
{" "}
Политикой конфиденциальности{" "}
</Link>
&ensp;ознакомлен
</Typography>
</Box>
<Box
sx={{
display: "flex",
alignItems: "center",
mt: "20px",
gap: "15px",
}}
>
<NameplateLogo
style={{
fontSize: "34px",
//@ts-ignore
color: mode[settings.cfg.theme] ? "#151515" : "#FFFFFF",
}}
/>
<Typography
sx={{
fontSize: "20px",
//@ts-ignore
color: mode[settings.cfg.theme] ? "#4D4D4D" : "#F5F7FF",
whiteSpace: "nowrap",
}}
>
Сделано на PenaQuiz
</Typography>
</Box>
</Box>
</Box>
</Box>
);
};
const Inputs = ({
name,
setName,
email,
setEmail,
phone,
setPhone,
text,
setText,
adress,
setAdress,
}: any) => {
const { settings } = useQuestionsStore();
// @ts-ignore
const FC = settings?.cfg.formContact.fields || settings?.cfg.formContact;
if (!FC) return null;
//@ts-ignore
const Name = (
<CustomInput
//@ts-ignore
onChange={({ target }) => setName(target.value)}
id={name}
title={FC["name"].innerText || "Введите имя"}
desc={FC["name"].text || "имя"}
Icon={NameIcon}
/>
);
//@ts-ignore
const Email = (
<CustomInput
error={!EMAIL_REGEXP.test(email)}
label={!EMAIL_REGEXP.test(email) ? "" : "Некорректная почта"}
//@ts-ignore
onChange={({ target }) => setEmail(target.value)}
id={email}
title={FC["email"].innerText || "Введите Email"}
desc={FC["email"].text || "Email"}
Icon={EmailIcon}
/>
);
const Phone = (
<CustomInput
//@ts-ignore
onChange={({ target }) => setPhone(target.value)}
id={phone}
title={FC["phone"].innerText || "Введите номер телефона"}
desc={FC["phone"].text || "номер телефона"}
Icon={PhoneIcon}
/>
);
//@ts-ignore
const Text = (
<CustomInput
//@ts-ignore
onChange={({ target }) => setText(target.value)}
id={text}
title={FC["text"].text || "Введите фамилию"}
desc={FC["text"].innerText || "фамилию"}
Icon={TextIcon}
/>
);
//@ts-ignore
const Adress = (
<CustomInput
//@ts-ignore
onChange={({ target }) => setAdress(target.value)}
id={adress}
title={FC["address"].innerText || "Введите адрес"}
desc={FC["address"].text || "адрес"}
Icon={AddressIcon}
/>
);
//@ts-ignore
if (Object.values(FC).some((data) => data.used)) {
return (
<>
{FC["name"].used ? Name : <></>}
{FC["email"].used ? Email : <></>}
{FC["phone"].used ? Phone : <></>}
{FC["text"].used ? Text : <></>}
{FC["address"].used ? Adress : <></>}
</>
);
} else {
return (
<>
{Name}
{Email}
{Phone}
</>
);
}
};
const CustomInput = ({ title, desc, Icon, onChange }: any) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
//@ts-ignore
return (
<Box m="15px 0">
<Typography mb="7px" color={theme.palette.text.primary}>
{title}
</Typography>
<TextField
onChange={onChange}
sx={{
width: isMobile ? "300px" : "350px",
}}
placeholder={desc}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Icon color="gray" />
</InputAdornment>
),
}}
/>
</Box>
);
};