feat: new ResultForm logic

This commit is contained in:
IlyaDoronin 2024-01-10 19:53:37 +03:00
parent 50d2b6cadc
commit 667a0cd069
14 changed files with 221 additions and 107 deletions

@ -17,5 +17,6 @@ export const QUIZ_QUESTION_RESULT: Omit<
price: [0],
useImage: true,
usage: true,
redirect: "",
},
};

@ -19,5 +19,6 @@ export interface QuizQuestionResult extends QuizQuestionBase {
hint: QuestionHint;
autofill: boolean;
usage: boolean;
redirect: string;
};
}

@ -65,12 +65,13 @@ export interface QuizConfig {
| "BlueTheme"
| "BlueDarkTheme";
resultInfo: {
when: "before" | "after" | "email";
when: "email" | "";
share: true | false;
replay: true | false;
theme: string;
reply: string;
replname: string;
showResultForm: "before" | "after";
};
startpage: {
description: string;
@ -133,12 +134,13 @@ export const defaultQuizConfig: QuizConfig = {
haveRoot: null,
theme: "StandardTheme",
resultInfo: {
when: "after",
when: "",
share: false,
replay: false,
theme: "",
reply: "",
replname: "",
showResultForm: "after",
},
startpage: {
description: "",

@ -265,19 +265,21 @@ const SettingField = ({
<GearIcon height="20px" width="20px" color="#7e2aea" />
</IconButton>
</Typography>
<IconButton
onClick={() =>
updateQuiz(quiz?.id, (quiz) => {
quiz.config.formContact.fields[type].used = false;
})
}
sx={{
width: "48px",
ml: "5px",
}}
>
<Trash />
</IconButton>
{(type !== "email" || quiz?.config.resultInfo.when !== "email") && (
<IconButton
onClick={() =>
updateQuiz(quiz?.id, (quiz) => {
quiz.config.formContact.fields[type].used = false;
})
}
sx={{
width: "48px",
ml: "5px",
}}
>
<Trash />
</IconButton>
)}
</Box>
</>
);

@ -113,7 +113,7 @@ export const ResultSettings = () => {
</Box>
<WhenCard quizExpand={quizExpand} />
{quiz.config.resultInfo.when === "email" && (
{quiz?.config.resultInfo.when === "email" && (
<EmailSettingsCard quizExpand={quizExpand} />
)}

@ -1,9 +1,10 @@
import * as React from "react";
import { useState, useEffect } from "react";
import {
getQuestionByContentId,
updateQuestion,
} from "@root/questions/actions";
import { useCurrentQuiz } from "@root/quizes/hooks";
import CustomTextField from "@ui_kit/CustomTextField";
@ -26,9 +27,12 @@ import ExpandLessIcon from "@mui/icons-material/ExpandLess";
import Trash from "@icons/trash";
import Info from "@icons/Info";
import SettingIcon from "@icons/questionsPage/settingIcon";
import { QuizQuestionResult } from "@model/questionTypes/result";
import { MediaSelectionAndDisplay } from "@ui_kit/MediaSelectionAndDisplay";
import type { MouseEvent } from "react";
import type { QuizQuestionResult } from "@model/questionTypes/result";
interface Props {
resultContract: boolean;
resultData: QuizQuestionResult;
@ -57,11 +61,9 @@ export const checkEmptyData = ({
const InfoView = ({ resultData }: { resultData: QuizQuestionResult }) => {
const checkEmpty = checkEmptyData({ resultData });
const question = getQuestionByContentId(resultData.content.rule.parentId);
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(
null,
);
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
@ -126,12 +128,23 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
const isMobile = useMediaQuery(theme.breakpoints.down(790));
const isTablet = useMediaQuery(theme.breakpoints.down(800));
const [expand, setExpand] = React.useState(true);
const [resultCardSettings, setResultCardSettings] = React.useState(false);
const [buttonPlus, setButtonPlus] = React.useState(true);
const [expand, setExpand] = useState(true);
const [resultCardSettings, setResultCardSettings] = useState(false);
const [buttonPlus, setButtonPlus] = useState(true);
const question = getQuestionByContentId(resultData.content.rule.parentId);
const quiz = useCurrentQuiz();
React.useEffect(() => {
useEffect(() => {
if (
resultData.content.hint.text ||
(quiz?.config.resultInfo.showResultForm === "after" &&
resultData.content.redirect)
) {
setButtonPlus(false);
}
}, []);
useEffect(() => {
setExpand(true);
}, [resultContract]);
@ -390,17 +403,13 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
<Trash />
</IconButton>
</Box>
<CustomTextField
value={resultData.content.hint.text}
onChange={({ target }: { target: HTMLInputElement }) =>
updateQuestion(
resultData.id,
(question) =>
(question.content.hint.text = target.value),
)
updateQuestion(resultData.id, (question) => {
question.content.hint.text = target.value;
})
}
fullWidth
maxLength={19}
placeholder="Например: узнать подробнее"
sx={{
@ -421,6 +430,49 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
},
}}
/>
{quiz?.config.resultInfo.showResultForm === "after" && (
<>
<Typography
sx={{
weight: "500",
fontSize: "18px",
margin: "10px 0",
}}
>
Cсылка для кнопки
</Typography>
<CustomTextField
value={resultData.content.redirect}
onChange={({ target }: { target: HTMLInputElement }) =>
updateQuestion<QuizQuestionResult>(
resultData.id,
(question) => {
question.content.redirect = target.value;
},
)
}
placeholder="https://penahub.ru"
sx={{
"& .MuiInputBase-root": {
backgroundColor: "#F2F3F7",
width: isMobile ? undefined : "409px",
height: "48px",
borderRadius: "8px",
},
}}
inputProps={{
sx: {
height: "85px",
borderRadius: "10px",
fontSize: "18px",
lineHeight: "21px",
py: 0,
},
}}
/>
</>
)}
</Box>
)}
</Box>

@ -22,7 +22,12 @@ import ExpandLessIcon from "@mui/icons-material/ExpandLess";
import ShareNetwork from "@icons/ShareNetwork.svg";
import ArrowCounterClockWise from "@icons/ArrowCounterClockWise.svg";
const whenValues = [
type WhenVariants = {
title: string;
value: "before" | "after";
};
const whenValues: WhenVariants[] = [
{
title: "До формы контактов",
value: "before",
@ -31,10 +36,6 @@ const whenValues = [
title: "После формы контактов",
value: "after",
},
{
title: "Отправить на E-mail",
value: "email",
},
];
interface Props {
@ -170,7 +171,7 @@ export const WhenCard = ({ quizExpand }: Props) => {
</IconButton>
</Box>
</Box>
{expand && (
{expand && quiz && (
<>
<Box
sx={{
@ -189,20 +190,20 @@ export const WhenCard = ({ quizExpand }: Props) => {
{whenValues.map(({ title, value }, index) => (
<Box display="flex">
<Button
onClick={() =>
updateQuiz(
quiz.id,
(quiz) => (quiz.config.resultInfo.when = value),
)
}
onClick={() => {
updateQuiz(quiz.id, (quiz) => {
quiz.config.resultInfo.showResultForm = value;
quiz.config;
});
}}
key={title}
sx={{
bgcolor:
quiz?.config.resultInfo.when === value
quiz?.config.resultInfo.showResultForm === value
? " #7E2AEA"
: "#F2F3F7",
color:
quiz?.config.resultInfo.when === value
quiz?.config.resultInfo.showResultForm === value
? " white"
: "#9A9AAF",
minWidth: isSmallMonitor
@ -215,12 +216,12 @@ export const WhenCard = ({ quizExpand }: Props) => {
height: "44px",
fontSize: "17px",
border:
quiz?.config.resultInfo.when === value
quiz?.config.resultInfo.showResultForm === value
? "none"
: "1px solid #9A9AAF",
"&:hover": {
backgroundColor:
quiz?.config.resultInfo.when === value
quiz?.config.resultInfo.showResultForm === value
? "#581CA7"
: "#7E2AEA",
color: "white",
@ -229,9 +230,59 @@ export const WhenCard = ({ quizExpand }: Props) => {
>
{title}
</Button>
{value === "email" && <InfoView />}
</Box>
))}
<Box>
<Button
onClick={() => {
updateQuiz(quiz.id, (quiz) => {
if (quiz.config.resultInfo.when) {
quiz.config.resultInfo.when = "";
return;
}
quiz.config.resultInfo.when = "email";
});
updateQuiz(quiz?.id, (quiz) => {
quiz.config.formContact.fields["email"].used = true;
});
}}
sx={{
bgcolor:
quiz?.config.resultInfo.when === "email"
? " #7E2AEA"
: "#F2F3F7",
color:
quiz?.config.resultInfo.when === "email"
? " white"
: "#9A9AAF",
minWidth: isSmallMonitor
? isMobile
? undefined
: "310px"
: "auto",
borderRadius: "8px",
width: isMobile ? "100%" : "220px",
height: "44px",
fontSize: "17px",
border:
quiz?.config.resultInfo.when === "email"
? "none"
: "1px solid #9A9AAF",
"&:hover": {
backgroundColor:
quiz?.config.resultInfo.when === "email"
? "#581CA7"
: "#7E2AEA",
color: "white",
},
}}
>
Отправить на E-mail
</Button>
<InfoView />
</Box>
</Box>
{/* {

@ -186,14 +186,14 @@ export const ContactForm = ({
{
// resultQuestion &&
// quiz?.config.resultInfo.when === "after" &&
// quiz?.config.resultInfo.showResultForm === "after" &&
<Button
disabled={!ready}
variant="contained"
onClick={() => {
if (
(quiz?.config.resultInfo.when === "after" ||
quiz?.config.resultInfo.when === "email") &&
quiz?.config.resultInfo.showResultForm === "after" &&
resultQuestion?.type === "result" &&
!checkEmptyData({ resultData: resultQuestion })
) {
setShowContactForm(false);

@ -22,6 +22,8 @@ import { NameplateLogoFQDark } from "@icons/NameplateLogoFQDark";
import { modes } from "../../utils/themes/Publication/themePublication";
import { checkEmptyData } from "../ResultPage/cards/ResultCard";
import type { QuizQuestionResult } from "@model/questionTypes/result";
type FooterProps = {
setCurrentQuestion: (step: AnyTypedQuizQuestion) => void;
question: AnyTypedQuizQuestion;
@ -108,28 +110,20 @@ export const Footer = ({
}
}, [question, answers]);
const showResult = (nextQuestion) => {
const showResult = (nextQuestion: QuizQuestionResult) => {
console.log("Следующий результат будет вот такой", nextQuestion);
if (nextQuestion && quiz?.config.resultInfo.when === "email") {
setShowContactForm(true);
return;
}
const isEmpty = checkEmptyData({ resultData: nextQuestion });
console.log("isEmpty", isEmpty);
if (nextQuestion) {
if (nextQuestion && quiz?.config.resultInfo.when === "before") {
if (nextQuestion && quiz?.config.resultInfo.showResultForm === "before") {
if (isEmpty) {
setShowContactForm(true); //до+пустая = кидать на ФК
} else {
setShowResultForm(true); //до+заполнена = показать
}
}
if (
nextQuestion &&
(quiz?.config.resultInfo.when === "after" ||
quiz?.config.resultInfo.when === "email")
) {
if (nextQuestion && quiz?.config.resultInfo.showResultForm === "after") {
if (isEmpty) {
setShowContactForm(true); //после+пустая
} else {

@ -105,14 +105,15 @@ export const Question = ({ questions }: QuestionProps) => {
</Box>
</Box>
)}
{showResultForm && quiz?.config.resultInfo.when === "before" && (
<ResultForm
currentQuestion={currentQuestion}
showContactForm={showContactForm}
setShowContactForm={setShowContactForm}
setShowResultForm={setShowResultForm}
/>
)}
{showResultForm &&
quiz?.config.resultInfo.showResultForm === "before" && (
<ResultForm
currentQuestion={currentQuestion}
showContactForm={showContactForm}
setShowContactForm={setShowContactForm}
setShowResultForm={setShowResultForm}
/>
)}
{showContactForm && (
<ContactForm
currentQuestion={currentQuestion}
@ -121,16 +122,14 @@ export const Question = ({ questions }: QuestionProps) => {
setShowResultForm={setShowResultForm}
/>
)}
{showResultForm &&
(quiz?.config.resultInfo.when === "after" ||
quiz?.config.resultInfo.when === "email") && (
<ResultForm
currentQuestion={currentQuestion}
showContactForm={showContactForm}
setShowContactForm={setShowContactForm}
setShowResultForm={setShowResultForm}
/>
)}
{showResultForm && quiz?.config.resultInfo.showResultForm === "after" && (
<ResultForm
currentQuestion={currentQuestion}
showContactForm={showContactForm}
setShowContactForm={setShowContactForm}
setShowResultForm={setShowResultForm}
/>
)}
{!showContactForm && !showResultForm && (
<Footer
question={currentQuestion}

@ -10,11 +10,13 @@ import { getQuestionByContentId } from "@root/questions/actions";
import { useCurrentQuiz } from "@root/quizes/hooks";
import { useQuestionsStore } from "@root/questions/store";
import type { AnyTypedQuizQuestion } from "../../model/questionTypes/shared";
import YoutubeEmbedIframe from "../../ui_kit/StartPagePreview/YoutubeEmbedIframe.tsx";
import { NameplateLogo } from "@icons/NameplateLogo";
import { modes } from "../../utils/themes/Publication/themePublication";
import type { AnyTypedQuizQuestion } from "../../model/questionTypes/shared";
import type { QuizQuestionResult } from "../../model/questionTypes/result";
type ResultFormProps = {
currentQuestion: AnyTypedQuizQuestion;
showContactForm: boolean;
@ -34,7 +36,7 @@ export const ResultForm = ({
const isMobile = useMediaQuery(theme.breakpoints.down(650));
const { questions } = useQuestionsStore();
const searchResult = () => {
const searchResult = (): QuizQuestionResult => {
if (Boolean(quiz?.config.haveRoot)) {
//ищём для ветвления
return (questions.find(
@ -46,13 +48,13 @@ export const ResultForm = ({
(question) =>
question.type === "result" &&
question.content.rule.parentId === "line",
)) as AnyTypedQuizQuestion;
)) as QuizQuestionResult;
} else {
return questions.find(
(question) =>
question.type === "result" &&
question.content.rule.parentId === "line",
) as AnyTypedQuizQuestion;
) as QuizQuestionResult;
}
};
@ -180,33 +182,41 @@ export const ResultForm = ({
</Box>
</Box>
{quiz?.config.resultInfo.when === "before" && (
<>
<Box
<Box
sx={{
boxShadow: "0 0 15px 0 rgba(0,0,0,.08)",
width: "100%",
flexDirection: "column",
display: "flex",
justifyContent: "center",
alignItems: "center",
p: "20px",
}}
>
{quiz?.config.resultInfo.showResultForm === "before" && (
<Button
onClick={followNextForm}
variant="contained"
sx={{
boxShadow: "0 0 15px 0 rgba(0,0,0,.08)",
width: "100%",
flexDirection: "column",
display: "flex",
justifyContent: "center",
alignItems: "center",
p: "20px",
p: "10px 20px",
width: "210px",
height: "50px",
}}
>
{resultQuestion.content.hint.text || "Узнать подробнее"}
</Button>
)}
{quiz?.config.resultInfo.showResultForm === "after" &&
resultQuestion.content.redirect && (
<Button
onClick={followNextForm}
href={resultQuestion.content.redirect}
variant="contained"
sx={{
p: "10px 20px",
width: "210px",
height: "50px",
}}
sx={{ p: "10px 20px", width: "210px", height: "50px" }}
>
{resultQuestion.content.hint.text || "Узнать подробнее"}
{resultQuestion.content.hint.text || "Перейти на сайт"}
</Button>
</Box>
</>
)}
)}
</Box>
</Box>
</Box>
);

@ -45,6 +45,7 @@ export const Page = ({ currentQuestion }: PageProps) => {
}}
>
<img
key={currentQuestion.id}
src={currentQuestion.content.back}
alt=""
style={{

@ -121,6 +121,7 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
currentQuestion.content.back !== " " && (
<Box sx={{ maxWidth: "400px", width: "100%", height: "300px" }}>
<img
key={currentQuestion.id}
src={currentQuestion.content.back}
style={{
width: "100%",

@ -11,7 +11,7 @@ export const replaceSpacesToEmptyLines = <T = unknown>(object: T): T => {
for (const [key, value] of Object.entries(object)) {
if (typeof value === "string") {
result[key] = value.replace(/\" \"/g, '""');
result[key] = value.replace(" ", "").replace(/\" \"/g, '""');
continue;
}