489 lines
15 KiB
TypeScript
489 lines
15 KiB
TypeScript
import { useState, useEffect } from "react";
|
||
|
||
import {
|
||
getQuestionByContentId,
|
||
updateQuestion,
|
||
} from "@root/questions/actions";
|
||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||
|
||
import CustomTextField from "@ui_kit/CustomTextField";
|
||
|
||
import {
|
||
Box,
|
||
IconButton,
|
||
Paper,
|
||
Button,
|
||
Typography,
|
||
TextField,
|
||
useMediaQuery,
|
||
useTheme,
|
||
FormControl,
|
||
Popover,
|
||
} from "@mui/material";
|
||
import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
|
||
|
||
import ExpandLessIconBG from "@icons/ExpandLessIconBG";
|
||
import ExpandLessIcon from "@mui/icons-material/ExpandLess";
|
||
import Trash from "@icons/trash";
|
||
import Info from "@icons/Info";
|
||
import SettingIcon from "@icons/questionsPage/settingIcon";
|
||
import { MediaSelectionAndDisplay } from "@ui_kit/MediaSelectionAndDisplay";
|
||
|
||
import type { MouseEvent } from "react";
|
||
|
||
import type { QuizQuestionResult } from "@model/questionTypes/result";
|
||
|
||
interface Props {
|
||
resultContract: boolean;
|
||
resultData: QuizQuestionResult;
|
||
}
|
||
|
||
export const checkEmptyData = ({
|
||
resultData,
|
||
}: {
|
||
resultData: QuizQuestionResult;
|
||
}) => {
|
||
let check = true;
|
||
if (
|
||
resultData.title?.length > 0 ||
|
||
resultData.description?.length > 0 ||
|
||
resultData.content.back?.length > 0 ||
|
||
resultData.content.originalBack?.length > 0 ||
|
||
resultData.content.innerName?.length > 0 ||
|
||
resultData.content.text?.length > 0 ||
|
||
resultData.content.video?.length > 0 ||
|
||
resultData.content.hint.text?.length > 0
|
||
)
|
||
check = false;
|
||
return check;
|
||
};
|
||
|
||
const InfoView = ({ resultData }: { resultData: QuizQuestionResult }) => {
|
||
const checkEmpty = checkEmptyData({ resultData });
|
||
const question = getQuestionByContentId(resultData.content.rule.parentId);
|
||
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
|
||
|
||
const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
|
||
setAnchorEl(event.currentTarget);
|
||
};
|
||
|
||
const handleClose = () => {
|
||
setAnchorEl(null);
|
||
};
|
||
|
||
const open = Boolean(anchorEl);
|
||
const id = open ? "simple-popover" : undefined;
|
||
|
||
return (
|
||
<>
|
||
<Info
|
||
sx={{
|
||
"MuiIconButton-root": {
|
||
boxShadow: "0 0 10px 10px red",
|
||
},
|
||
}}
|
||
className={checkEmpty ? "blink" : ""}
|
||
onClick={handleClick}
|
||
/>
|
||
<Popover
|
||
id={id}
|
||
open={open}
|
||
anchorEl={anchorEl}
|
||
onClose={handleClose}
|
||
anchorOrigin={{
|
||
vertical: "bottom",
|
||
horizontal: "left",
|
||
}}
|
||
>
|
||
<Paper
|
||
sx={{
|
||
p: "20px",
|
||
display: "flex",
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
flexDirection: "column",
|
||
}}
|
||
>
|
||
<Typography>
|
||
{resultData?.content.rule.parentId === "line"
|
||
? "Единый результат в конце прохождения опроса без ветвления"
|
||
: `Заголовок вопроса, после которого появится результат: "${
|
||
question?.title || "нет заголовка"
|
||
}"`}
|
||
</Typography>
|
||
{checkEmpty && (
|
||
<Typography color="red">
|
||
Вы не заполнили этот результат никакими данными
|
||
</Typography>
|
||
)}
|
||
</Paper>
|
||
</Popover>
|
||
</>
|
||
);
|
||
};
|
||
|
||
export const ResultCard = ({ resultContract, resultData }: Props) => {
|
||
const theme = useTheme();
|
||
|
||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||
const isTablet = useMediaQuery(theme.breakpoints.down(800));
|
||
|
||
const [expand, setExpand] = useState(true);
|
||
const [resultCardSettings, setResultCardSettings] = useState(false);
|
||
const [buttonPlus, setButtonPlus] = useState(true);
|
||
const [inputValue, setInputValue] = useState(resultData.content.text);
|
||
const question = getQuestionByContentId(resultData.content.rule.parentId);
|
||
const quiz = useCurrentQuiz();
|
||
|
||
useEffect(() => {
|
||
if (
|
||
resultData.content.hint.text ||
|
||
(quiz?.config.resultInfo.showResultForm === "after" &&
|
||
resultData.content.redirect)
|
||
) {
|
||
setButtonPlus(false);
|
||
}
|
||
}, []);
|
||
|
||
useEffect(() => {
|
||
setExpand(true);
|
||
}, [resultContract]);
|
||
|
||
return (
|
||
<Paper
|
||
data-cy="quiz-question-card"
|
||
sx={{
|
||
maxWidth: "796px",
|
||
width: "100%",
|
||
borderRadius: "12px",
|
||
backgroundColor: expand ? "white" : "#EEE4FC",
|
||
border: expand ? "none" : "1px solid #9A9AAF",
|
||
boxShadow: "0px 10px 30px #e7e7e7",
|
||
m: "20px 0",
|
||
}}
|
||
>
|
||
<Typography sx={{ color: theme.palette.grey2.main, padding: "5px 20px" }}>
|
||
{resultData?.content.rule.parentId === "line"
|
||
? "Единый результат в конце прохождения опроса без ветвления"
|
||
: `Заголовок вопроса, после которого появится результат: "${
|
||
question?.title || "нет заголовка"
|
||
}"`}
|
||
</Typography>
|
||
<Box
|
||
sx={{
|
||
display: expand ? "none" : "flex",
|
||
alignItems: "center",
|
||
padding: isMobile ? "10px" : "0 20px 20px",
|
||
justifyContent: "space-between",
|
||
minHeight: "40px",
|
||
}}
|
||
>
|
||
<FormControl
|
||
variant="standard"
|
||
sx={{
|
||
p: 0,
|
||
maxWidth: isTablet ? "549px" : "640px",
|
||
width: "100%",
|
||
marginRight: isMobile ? "0px" : "16.1px",
|
||
}}
|
||
>
|
||
<CustomTextField
|
||
value={resultData.title}
|
||
placeholder={"Заголовок результата"}
|
||
maxLength={200}
|
||
onChange={({ target }: { target: HTMLInputElement }) =>
|
||
updateQuestion(
|
||
resultData.id,
|
||
(question) => (question.title = target.value),
|
||
)
|
||
}
|
||
sx={{
|
||
margin: isMobile ? "10px 0" : 0,
|
||
backgroundColor: expand
|
||
? theme.palette.background.default
|
||
: "transparent",
|
||
height: "48px",
|
||
borderRadius: "10px",
|
||
borderWidth: "1px !important",
|
||
border: !expand ? "none" : null,
|
||
"&::placeholder": {
|
||
color: "#4D4D4D",
|
||
opacity: 0.8,
|
||
},
|
||
}}
|
||
/>
|
||
</FormControl>
|
||
<Box
|
||
sx={{
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "flex-end",
|
||
width: "auto",
|
||
position: "relative",
|
||
}}
|
||
>
|
||
<IconButton
|
||
sx={{ padding: "0", margin: "5px" }}
|
||
disableRipple
|
||
data-cy="expand-question"
|
||
onClick={() => setExpand(!expand)}
|
||
>
|
||
{expand ? (
|
||
<ExpandLessIconBG />
|
||
) : (
|
||
<ExpandLessIcon
|
||
sx={{
|
||
boxSizing: "border-box",
|
||
fill: theme.palette.brightPurple.main,
|
||
background: "#FFF",
|
||
borderRadius: "6px",
|
||
height: "30px",
|
||
width: "30px",
|
||
}}
|
||
/>
|
||
)}
|
||
</IconButton>
|
||
<InfoView resultData={resultData} />
|
||
</Box>
|
||
</Box>
|
||
{expand && (
|
||
<>
|
||
<Box
|
||
sx={{
|
||
overflow: "hidden",
|
||
maxWidth: "796px",
|
||
height: "100%",
|
||
bgcolor: "#FFFFFF",
|
||
borderRadius: "12px",
|
||
boxShadow: "0px 10px 30px #e7e7e7",
|
||
}}
|
||
>
|
||
<Box sx={{ p: "0 20px", pt: "10px" }}>
|
||
<Box
|
||
sx={{
|
||
width: "100%",
|
||
maxWidth: "760px",
|
||
display: "flex",
|
||
alignItems: "center",
|
||
gap: "10px",
|
||
mb: "19px",
|
||
}}
|
||
>
|
||
<CustomTextField
|
||
id="headline-is-bolder"
|
||
value={resultData.description}
|
||
onChange={({ target }: { target: HTMLInputElement }) =>
|
||
updateQuestion(
|
||
resultData.id,
|
||
(question) => (question.description = target.value),
|
||
)
|
||
}
|
||
placeholder={"Заголовок пожирнее"}
|
||
maxLength={200}
|
||
sx={{
|
||
borderRadius: "8px",
|
||
height: "48px",
|
||
width: "100%",
|
||
}}
|
||
/>
|
||
<IconButton
|
||
sx={{ padding: "0", margin: "5px" }}
|
||
disableRipple
|
||
data-cy="expand-question"
|
||
onClick={() => setExpand(!expand)}
|
||
>
|
||
<ExpandLessIconBG />
|
||
</IconButton>
|
||
<InfoView resultData={resultData} />
|
||
</Box>
|
||
|
||
<Box
|
||
sx={{
|
||
margin: "20px 0",
|
||
}}
|
||
>
|
||
<CustomTextField
|
||
id="heading-result"
|
||
value={resultData.title}
|
||
placeholder={"Заголовок результата"}
|
||
maxLength={200}
|
||
onChange={({ target }: { target: HTMLInputElement }) =>
|
||
updateQuestion(
|
||
resultData.id,
|
||
(question) => (question.title = target.value),
|
||
)
|
||
}
|
||
/>
|
||
</Box>
|
||
|
||
<TextField
|
||
id="heading-description"
|
||
value={inputValue}
|
||
onChange={({ target }: { target: HTMLInputElement }) => {
|
||
if (target.value.length <= 3000) {
|
||
setInputValue(target.value);
|
||
}
|
||
updateQuestion(
|
||
resultData.id,
|
||
(question) => (question.content.text = target.value),
|
||
);
|
||
}}
|
||
fullWidth
|
||
placeholder="Описание"
|
||
multiline
|
||
rows={4}
|
||
sx={{
|
||
"& .MuiInputBase-root": {
|
||
backgroundColor: "#F2F3F7",
|
||
width: "100%",
|
||
height: "110px",
|
||
borderRadius: "10px",
|
||
},
|
||
}}
|
||
inputProps={{
|
||
sx: {
|
||
height: "85px",
|
||
borderRadius: "10px",
|
||
fontSize: "18px",
|
||
lineHeight: "21px",
|
||
py: 0,
|
||
},
|
||
}}
|
||
/>
|
||
|
||
<MediaSelectionAndDisplay
|
||
resultData={resultData}
|
||
cropAspectRatio={{ width: 305.9, height: 305.9 }}
|
||
/>
|
||
|
||
{buttonPlus ? (
|
||
<Button
|
||
data-cy="add-button"
|
||
onClick={() => {
|
||
setButtonPlus(false);
|
||
}}
|
||
sx={{
|
||
display: "inline flex",
|
||
height: "48px",
|
||
padding: "10px 20px",
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
gap: "8px",
|
||
flexShrink: 0,
|
||
borderRadius: "8px",
|
||
border: "1px solid #9A9AAF",
|
||
background: " #F2F3F7",
|
||
color: "#9A9AAF",
|
||
my: "30px",
|
||
}}
|
||
>
|
||
Кнопка +
|
||
</Button>
|
||
) : (
|
||
<Box
|
||
sx={{
|
||
my: "30px",
|
||
}}
|
||
>
|
||
<Box>
|
||
<Typography
|
||
component={"span"}
|
||
sx={{ weight: "500", fontSize: "18px", mb: "10px" }}
|
||
>
|
||
Призыв к действию
|
||
</Typography>
|
||
<IconButton
|
||
onClick={() => {
|
||
setButtonPlus(true);
|
||
updateQuestion(
|
||
resultData.id,
|
||
(q) => (q.content.hint.text = ""),
|
||
);
|
||
}}
|
||
>
|
||
<Trash />
|
||
</IconButton>
|
||
</Box>
|
||
<CustomTextField
|
||
id="button-text-result"
|
||
value={resultData.content.hint.text}
|
||
onChange={({ target }: { target: HTMLInputElement }) =>
|
||
updateQuestion(resultData.id, (question) => {
|
||
question.content.hint.text = target.value;
|
||
})
|
||
}
|
||
maxLength={19}
|
||
placeholder="Например: узнать подробнее"
|
||
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,
|
||
},
|
||
}}
|
||
/>
|
||
|
||
{quiz?.config.resultInfo.showResultForm === "after" && (
|
||
<>
|
||
<Typography
|
||
sx={{
|
||
weight: "500",
|
||
fontSize: "18px",
|
||
margin: "10px 0",
|
||
}}
|
||
>
|
||
Cсылка для кнопки
|
||
</Typography>
|
||
<CustomTextField
|
||
id="link-page-result"
|
||
value={resultData.content.redirect}
|
||
onChange={({ target }: { target: HTMLInputElement }) =>
|
||
updateQuestion<QuizQuestionResult>(
|
||
resultData.id,
|
||
(question) => {
|
||
question.content.redirect = target.value;
|
||
},
|
||
)
|
||
}
|
||
placeholder="https://penahub.ru"
|
||
maxLength={200}
|
||
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>
|
||
</Box>
|
||
</>
|
||
)}
|
||
</Paper>
|
||
);
|
||
};
|