frontPanel/src/pages/ResultPage/cards/ResultCard.tsx

611 lines
19 KiB
TypeScript
Raw Normal View History

import * as React from "react";
import { getQuestionByContentId, updateQuestion, uploadQuestionImage } from "@root/questions/actions"
import { useCurrentQuiz } from "@root/quizes/hooks"
import CustomTextField from "@ui_kit/CustomTextField";
import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal";
import { UploadImageModal } from "../../Questions/UploadImage/UploadImageModal";
import { useDisclosure } from "../../../utils/useDisclosure";
import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton";
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 { QuizQuestionResult } from "@model/questionTypes/result";
import { MutableRefObject } from "react";
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] = React.useState<HTMLButtonElement | null>(null);
const handleClick = (event: React.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) => {
console.log("resultData", resultData)
const quizQid = useCurrentQuiz()?.qid;
const theme = useTheme();
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)
React.useEffect(() => {
setExpand(true)
}, [resultContract])
const {
isCropModalOpen,
openCropModal,
closeCropModal,
imageBlob,
originalImageUrl,
setCropModalImageBlob,
} = useCropModalState();
const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] = useDisclosure();
async function handleImageUpload(file: File) {
const url = await uploadQuestionImage(resultData.id, quizQid, file, (question, url) => {
question.content.back = url;
question.content.originalBack = url;
});
closeImageUploadModal();
openCropModal(file, url);
}
function handleCropModalSaveClick(imageBlob: Blob) {
uploadQuestionImage(resultData.id, quizQid, imageBlob, (question, url) => {
question.content.back = url;
});
}
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"
}}
>
<Box
sx={{
display: expand ? "none" : "flex",
alignItems: "center",
padding: isMobile ? "10px" : "20px",
flexDirection: isMobile ? "column" : null,
justifyContent: "space-between",
minHeight: "40px",
}}
>
<FormControl
variant="standard"
sx={{
p: 0,
maxWidth: isTablet ? "549px" : "640px",
width: "100%",
marginRight: isMobile ? "0px" : "16.1px",
}}
>
<TextField
value={resultData.title}
placeholder={"Заголовок результата"}
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, question => question.title = target.value)}
sx={{
margin: isMobile ? "10px 0" : 0,
"& .MuiInputBase-root": {
color: "#000000",
backgroundColor: expand
? theme.palette.background.default
: "transparent",
height: "48px",
borderRadius: "10px",
".MuiOutlinedInput-notchedOutline": {
borderWidth: "1px !important",
border: !expand ? "none" : null,
},
"& .MuiInputBase-input::placeholder": {
color: "#4D4D4D",
opacity: 0.8,
},
},
}}
inputProps={{
sx: {
p: 0,
fontSize: "18px",
lineHeight: "21px",
},
}}
/>
</FormControl>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
width: isMobile ? "100%" : "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: "30px" }}>
<Box
sx={{
width: "100%",
maxWidth: "760px",
display: "flex",
alignItems: "center",
gap: "10px",
mb: "19px",
}}
>
<CustomTextField
value={resultData.title}
placeholder={"Заголовок результата"}
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, question => question.title = target.value)} />
<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
value={resultData.description}
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, (question) => question.description = target.value)}
placeholder={"Заголовок пожирнее"}
sx={{
borderRadius: "8px",
height: "48px",
width: "100%",
}}
/>
</Box>
<TextField
value={resultData.content.text}
onChange={({ target }: { target: HTMLInputElement; }) => 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,
},
}}
/>
<Box
sx={{
mt: "20px",
display: "flex",
gap: "10px",
flexDirection: "column"
}}
>
<Box
sx={{
display: "flex",
}}
>
<Button
sx={{
color: resultData.content.useImage ? "#7E2AEA" : "#9A9AAF",
fontSize: "16px",
"&:hover": {
background: "none",
},
}}
variant="text"
onClick={() => updateQuestion(resultData.id, (question) => question.content.useImage = true)}
>
Изображение
</Button>
<Button
sx={{
color: resultData.content.useImage ? "#9A9AAF" : "#7E2AEA",
fontSize: "16px",
"&:hover": {
background: "none",
},
}}
variant="text"
onClick={() => updateQuestion(resultData.id, (question) => question.content.useImage = false)}
>
Видео
</Button>
</Box>
<Box
sx={{
display: "flex",
flexDirection: "column",
}}
>
<UploadImageModal
isOpen={isImageUploadOpen}
onClose={closeImageUploadModal}
handleImageChange={handleImageUpload}
/>
<CropModal
isOpen={isCropModalOpen}
imageBlob={imageBlob}
originalImageUrl={originalImageUrl}
setCropModalImageBlob={setCropModalImageBlob}
onClose={closeCropModal}
onSaveImageClick={handleCropModalSaveClick}
/>
</Box>
{
resultData.content.useImage &&
<Box
sx={{
cursor: "pointer",
display: "flex",
alignItems: "center",
gap: "20px",
mb: "30px"
}}
>
<AddOrEditImageButton
imageSrc={resultData.content.back}
onImageClick={() => {
if (resultData.content.back) {
return openCropModal(
resultData.content.back,
resultData.content.originalBack
);
}
openImageUploadModal();
}}
onPlusClick={() => {
openImageUploadModal();
}}
/>
</Box>
}
{
!resultData.content.useImage &&
<Box
sx={{
cursor: "pointer",
display: "flex",
alignItems: "center",
gap: "20px",
mb: "30px"
}}
>
<CustomTextField
placeholder="URL видео"
text={resultData.content.video ?? ""}
onChange={e => updateQuestion(resultData.id, q => {
2023-12-16 12:33:06 +00:00
q.content.video = e.target.value;
})}
/>
</Box>
}
</Box>
{
buttonPlus ?
<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",
mb: "30px"
}}
>
Кнопка +
</Button>
:
<Box
sx={{
mb: "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>
<TextField
value={resultData.content.hint.text}
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, (question) => question.content.hint.text = target.value)}
fullWidth
placeholder="Например: узнать подробнее"
sx={{
"& .MuiInputBase-root": {
backgroundColor: "#F2F3F7",
width: "409px",
height: "48px",
borderRadius: "8px",
},
}}
inputProps={{
sx: {
height: "85px",
borderRadius: "10px",
fontSize: "18px",
lineHeight: "21px",
py: 0,
},
}}
/>
</Box>
}
</Box>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
width: "100%",
background: "#F2F3F7",
}}
>
<Box
sx={{
padding: "20px",
display: "flex",
flexWrap: "wrap",
gap: "10px",
}}
>
<MiniButtonSetting
onClick={() => {
setResultCardSettings(!resultCardSettings)
}}
sx={{
backgroundColor:
resultCardSettings
? theme.palette.brightPurple.main
: "transparent",
color:
resultCardSettings ? "#ffffff" : theme.palette.grey3.main,
"&:hover": {
backgroundColor: resultCardSettings ? "#581CA7" : "#7E2AEA",
color: "white"
}
}}
>
<SettingIcon
color={
resultCardSettings ? "#ffffff" : theme.palette.grey3.main
}
/>
{!isTablet && "Настройки"}
</MiniButtonSetting>
</Box>
</Box>
</Box>
{
resultCardSettings &&
<Box
sx={{
backgroundColor: "white",
p: "20px",
borderRadius: "0 0 12px 12px"
}}
>
<CustomTextField
placeholder={"Внутреннее описание вопроса"}
value={resultData.innerName}
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, (question) => question.content.innerName = target.value)}
/>
</Box>
}
</>
)
}
</Paper >
)
}