- create MediaSelectionAndDisplay

This commit is contained in:
ArtChaos189 2023-12-20 23:25:58 +03:00
parent 25bdf1ba87
commit 494d750534
3 changed files with 276 additions and 505 deletions

@ -1,18 +1,13 @@
import { VideofileIcon } from "@icons/questionsPage/VideofileIcon"; import { Box, useMediaQuery, useTheme } from "@mui/material";
import { Box, Button, Typography, useMediaQuery, useTheme } from "@mui/material"; import { updateQuestion } from "@root/questions/actions";
import { updateQuestion, uploadQuestionImage } from "@root/questions/actions";
import { useCurrentQuiz } from "@root/quizes/hooks";
import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton";
import CustomTextField from "@ui_kit/CustomTextField"; import CustomTextField from "@ui_kit/CustomTextField";
import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal";
import { useState } from "react"; import { useState } from "react";
import { useDebouncedCallback } from "use-debounce"; import { useDebouncedCallback } from "use-debounce";
import type { QuizQuestionPage } from "../../../model/questionTypes/page"; import type { QuizQuestionPage } from "../../../model/questionTypes/page";
import ButtonsOptions from "../ButtonsOptions"; import ButtonsOptions from "../ButtonsOptions";
import { UploadImageModal } from "../UploadImage/UploadImageModal";
import { UploadVideoModal } from "../UploadVideoModal";
import SwitchPageOptions from "./switchPageOptions"; import SwitchPageOptions from "./switchPageOptions";
import { useDisclosure } from "../../../utils/useDisclosure"; import { MediaSelectionAndDisplay } from "@ui_kit/MediaSelectionAndDisplay";
type Props = { type Props = {
disableInput?: boolean; disableInput?: boolean;
@ -20,16 +15,11 @@ type Props = {
}; };
export default function PageOptions({ disableInput, question }: Props) { export default function PageOptions({ disableInput, question }: Props) {
const [openVideoModal, setOpenVideoModal] = useState<boolean>(false);
const [switchState, setSwitchState] = useState("setting"); const [switchState, setSwitchState] = useState("setting");
const theme = useTheme(); const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(980)); const isTablet = useMediaQuery(theme.breakpoints.down(980));
const isFigmaTablet = useMediaQuery(theme.breakpoints.down(990)); const isFigmaTablet = useMediaQuery(theme.breakpoints.down(990));
const isMobile = useMediaQuery(theme.breakpoints.down(780)); const isMobile = useMediaQuery(theme.breakpoints.down(780));
const quizQid = useCurrentQuiz()?.qid;
const { isCropModalOpen, openCropModal, closeCropModal, imageBlob, originalImageUrl, setCropModalImageBlob } =
useCropModalState();
const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] = useDisclosure();
const setText = useDebouncedCallback((value) => { const setText = useDebouncedCallback((value) => {
updateQuestion(question.id, (question) => { updateQuestion(question.id, (question) => {
@ -43,27 +33,6 @@ export default function PageOptions({ disableInput, question }: Props) {
setSwitchState(data); setSwitchState(data);
}; };
async function handleImageUpload(file: File) {
const url = await uploadQuestionImage(question.id, quizQid, file, (question, url) => {
if (question.type !== "page") return;
question.content.picture = url;
question.content.originalPicture = url;
});
closeImageUploadModal();
openCropModal(file, url);
}
function handleCropModalSaveClick(imageBlob: Blob) {
uploadQuestionImage(question.id, quizQid, imageBlob, (question, url) => {
if (question.type !== "page") return;
question.content.picture = url;
});
}
console.log(question.content.useImage);
return ( return (
<> <>
<Box <Box
@ -73,7 +42,6 @@ export default function PageOptions({ disableInput, question }: Props) {
display: "flex", display: "flex",
px: "20px", px: "20px",
flexDirection: "column", flexDirection: "column",
gap: isMobile ? "25px" : "20px",
}} }}
> >
<Box sx={{ display: disableInput ? "none" : "", mt: isMobile ? "15px" : "0px" }}> <Box sx={{ display: disableInput ? "none" : "", mt: isMobile ? "15px" : "0px" }}>
@ -84,179 +52,7 @@ export default function PageOptions({ disableInput, question }: Props) {
/> />
</Box> </Box>
<Box <MediaSelectionAndDisplay resultData={question} />
sx={{
mb: "20px",
ml: isTablet ? "0px" : "60px",
display: "flex",
alignItems: "center",
gap: "28px",
justifyContent: isMobile ? "space-between" : null,
}}
>
<Box
sx={{
cursor: "pointer",
display: "flex",
alignItems: "center",
gap: "20px",
}}
>
<AddOrEditImageButton
imageSrc={question.content.picture}
onImageClick={() => {
if (question.content.picture) {
return openCropModal(question.content.picture, question.content.originalPicture);
}
openImageUploadModal();
}}
onPlusClick={() => {
openImageUploadModal();
}}
/>
<Typography
sx={{
display: isMobile ? "none" : "block",
fontWeight: 400,
fontSize: "16px",
lineHeight: "18.96px",
color: question.content.useImage ? "#7E2AEA" : "#9A9AAF",
}}
onClick={() =>
updateQuestion(question.id, (question) => ((question as QuizQuestionPage).content.useImage = true))
}
>
Изображение
</Typography>
</Box>
<UploadImageModal
isOpen={isImageUploadOpen}
onClose={closeImageUploadModal}
handleImageChange={handleImageUpload}
/>
<CropModal
isOpen={isCropModalOpen}
imageBlob={imageBlob}
originalImageUrl={originalImageUrl}
setCropModalImageBlob={setCropModalImageBlob}
onClose={closeCropModal}
onSaveImageClick={handleCropModalSaveClick}
/>
<Typography> или</Typography>
<Box
sx={{
cursor: "pointer",
display: "flex",
alignItems: "center",
gap: "10px",
}}
>
{isMobile ? (
<Box
sx={{
display: "flex",
alignItems: "center",
width: "120px",
position: "relative",
}}
>
<Box
sx={{
width: "100%",
background: "#EEE4FC",
height: "40px",
display: "flex",
alignItems: "center",
justifyContent: "center",
borderTopLeftRadius: "4px",
borderBottomLeftRadius: "4px",
}}
>
<VideofileIcon
style={{
color: "#7E2AEA",
fontSize: "20px",
}}
/>
</Box>
<Box
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
width: "20px",
background: "#EEE4FC",
height: "40px",
color: "white",
backgroundColor: "#7E2AEA",
borderTopRightRadius: "4px",
borderBottomRightRadius: "4px",
}}
>
+
</Box>
</Box>
) : (
<Box
sx={{
width: "60px",
height: "40px",
background: "#EEE4FC",
display: "flex",
justifyContent: "space-between",
}}
>
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "center", width: "100%" }}>
<VideofileIcon fontSize="22px" color="#7E2AEA" />
</Box>
<span
onClick={() => setOpenVideoModal(true)}
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
background: "#7E2AEA",
height: "100%",
width: "25px",
color: "white",
fontSize: "15px",
}}
>
+
</span>
</Box>
)}
<Typography
sx={{
display: isMobile ? "none" : "block",
fontWeight: 400,
fontSize: "16px",
lineHeight: "18.96px",
color: question.content.useImage ? "#9A9AAF" : "#7E2AEA",
}}
onClick={() =>
updateQuestion(question.id, (question) => ((question as QuizQuestionPage).content.useImage = false))
}
>
Видео
</Typography>
</Box>
<UploadVideoModal
open={openVideoModal}
onClose={() => setOpenVideoModal(false)}
video={question.content.video}
onUpload={(url) => {
updateQuestion(question.id, (question) => {
if (question.type !== "page") return;
question.content.video = url;
});
}}
/>
</Box>
</Box> </Box>
<ButtonsOptions switchState={switchState} SSHC={SSHC} question={question} /> <ButtonsOptions switchState={switchState} SSHC={SSHC} question={question} />
<SwitchPageOptions switchState={switchState} question={question} /> <SwitchPageOptions switchState={switchState} question={question} />

@ -1,14 +1,8 @@
import * as React from "react"; import * as React from "react";
import { getQuestionByContentId, updateQuestion, uploadQuestionImage } from "@root/questions/actions" import { getQuestionByContentId, updateQuestion } from "@root/questions/actions";
import { useCurrentQuiz } from "@root/quizes/hooks"
import CustomTextField from "@ui_kit/CustomTextField"; 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 { import {
Box, Box,
@ -20,7 +14,7 @@ import {
useMediaQuery, useMediaQuery,
useTheme, useTheme,
FormControl, FormControl,
Popover Popover,
} from "@mui/material"; } from "@mui/material";
import MiniButtonSetting from "@ui_kit/MiniButtonSetting"; import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
@ -30,7 +24,7 @@ import Trash from "@icons/trash";
import Info from "@icons/Info"; import Info from "@icons/Info";
import SettingIcon from "@icons/questionsPage/settingIcon"; import SettingIcon from "@icons/questionsPage/settingIcon";
import { QuizQuestionResult } from "@model/questionTypes/result"; import { QuizQuestionResult } from "@model/questionTypes/result";
import { MutableRefObject } from "react"; import { MediaSelectionAndDisplay } from "@ui_kit/MediaSelectionAndDisplay";
interface Props { interface Props {
resultContract: boolean; resultContract: boolean;
@ -38,7 +32,7 @@ interface Props {
} }
export const checkEmptyData = ({ resultData }: { resultData: QuizQuestionResult }) => { export const checkEmptyData = ({ resultData }: { resultData: QuizQuestionResult }) => {
let check = true let check = true;
if ( if (
resultData.title.length > 0 || resultData.title.length > 0 ||
resultData.description.length > 0 || resultData.description.length > 0 ||
@ -47,14 +41,15 @@ export const checkEmptyData = ({ resultData }: { resultData: QuizQuestionResult
resultData.content.innerName.length > 0 || resultData.content.innerName.length > 0 ||
resultData.content.text.length > 0 || resultData.content.text.length > 0 ||
resultData.content.video.length > 0 || resultData.content.video.length > 0 ||
resultData.content.hint.text.length > 0 resultData.content.hint.text.length > 0
) check = false )
return check check = false;
} return check;
};
const InfoView = ({ resultData }: { resultData: QuizQuestionResult }) => { const InfoView = ({ resultData }: { resultData: QuizQuestionResult }) => {
const checkEmpty = checkEmptyData({ resultData }) const checkEmpty = checkEmptyData({ resultData });
const question = getQuestionByContentId(resultData.content.rule.parentId) const question = getQuestionByContentId(resultData.content.rule.parentId);
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null); const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => { const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
@ -66,20 +61,18 @@ const InfoView = ({ resultData }: { resultData: QuizQuestionResult }) => {
}; };
const open = Boolean(anchorEl); const open = Boolean(anchorEl);
const id = open ? 'simple-popover' : undefined; const id = open ? "simple-popover" : undefined;
return ( return (
<> <>
<Info <Info
sx={{ sx={{
"MuiIconButton-root": { "MuiIconButton-root": {
boxShadow: "0 0 10px 10px red",
boxShadow: "0 0 10px 10px red" },
}
}} }}
className={checkEmpty ? "blink" : ""} className={checkEmpty ? "blink" : ""}
onClick={handleClick} onClick={handleClick}
/> />
<Popover <Popover
id={id} id={id}
@ -87,85 +80,44 @@ const InfoView = ({ resultData }: { resultData: QuizQuestionResult }) => {
anchorEl={anchorEl} anchorEl={anchorEl}
onClose={handleClose} onClose={handleClose}
anchorOrigin={{ anchorOrigin={{
vertical: 'bottom', vertical: "bottom",
horizontal: 'left', horizontal: "left",
}} }}
> >
<Paper <Paper
sx={{ sx={{
p: '20px', p: "20px",
display: "flex", display: "flex",
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
flexDirection: "column" flexDirection: "column",
}} }}
> >
<Typography> <Typography>
{resultData?.content.rule.parentId === "line" ? "Единый результат в конце прохождения опросника без ветвления" {resultData?.content.rule.parentId === "line"
: ? "Единый результат в конце прохождения опросника без ветвления"
`Заголовок вопроса, после которого появится результат: "${question?.title || "нет заголовка"}"` : `Заголовок вопроса, после которого появится результат: "${question?.title || "нет заголовка"}"`}
}
</Typography> </Typography>
{checkEmpty && {checkEmpty && <Typography color="red">Вы не заполнили этот результат никакими данными</Typography>}
<Typography color="red">
Вы не заполнили этот результат никакими данными
</Typography>
}
</Paper> </Paper>
</Popover> </Popover>
</> </>
) );
} };
export const ResultCard = ({ resultContract, resultData }: Props) => { export const ResultCard = ({ resultContract, resultData }: Props) => {
const quizQid = useCurrentQuiz()?.qid;
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const isTablet = useMediaQuery(theme.breakpoints.down(800)); const isTablet = useMediaQuery(theme.breakpoints.down(800));
const [expand, setExpand] = React.useState(true) const [expand, setExpand] = React.useState(true);
const [resultCardSettings, setResultCardSettings] = React.useState(false) const [resultCardSettings, setResultCardSettings] = React.useState(false);
const [buttonPlus, setButtonPlus] = React.useState(true) const [buttonPlus, setButtonPlus] = React.useState(true);
React.useEffect(() => { React.useEffect(() => {
setExpand(true) setExpand(true);
}, [resultContract]) }, [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 ( return (
<Paper <Paper
@ -177,7 +129,7 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
backgroundColor: expand ? "white" : "#EEE4FC", backgroundColor: expand ? "white" : "#EEE4FC",
border: expand ? "none" : "1px solid #9A9AAF", border: expand ? "none" : "1px solid #9A9AAF",
boxShadow: "0px 10px 30px #e7e7e7", boxShadow: "0px 10px 30px #e7e7e7",
m: "20px 0" m: "20px 0",
}} }}
> >
<Box <Box
@ -188,7 +140,6 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
flexDirection: isMobile ? "column" : null, flexDirection: isMobile ? "column" : null,
justifyContent: "space-between", justifyContent: "space-between",
minHeight: "40px", minHeight: "40px",
}} }}
> >
<FormControl <FormControl
@ -203,14 +154,14 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
<TextField <TextField
value={resultData.title} value={resultData.title}
placeholder={"Заголовок результата"} placeholder={"Заголовок результата"}
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, question => question.title = target.value)} onChange={({ target }: { target: HTMLInputElement }) =>
updateQuestion(resultData.id, (question) => (question.title = target.value))
}
sx={{ sx={{
margin: isMobile ? "10px 0" : 0, margin: isMobile ? "10px 0" : 0,
"& .MuiInputBase-root": { "& .MuiInputBase-root": {
color: "#000000", color: "#000000",
backgroundColor: expand backgroundColor: expand ? theme.palette.background.default : "transparent",
? theme.palette.background.default
: "transparent",
height: "48px", height: "48px",
borderRadius: "10px", borderRadius: "10px",
".MuiOutlinedInput-notchedOutline": { ".MuiOutlinedInput-notchedOutline": {
@ -291,7 +242,10 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
<CustomTextField <CustomTextField
value={resultData.title} value={resultData.title}
placeholder={"Заголовок результата"} placeholder={"Заголовок результата"}
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, question => question.title = target.value)} /> onChange={({ target }: { target: HTMLInputElement }) =>
updateQuestion(resultData.id, (question) => (question.title = target.value))
}
/>
<IconButton <IconButton
sx={{ padding: "0", margin: "5px" }} sx={{ padding: "0", margin: "5px" }}
disableRipple disableRipple
@ -301,18 +255,18 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
<ExpandLessIconBG /> <ExpandLessIconBG />
</IconButton> </IconButton>
<InfoView resultData={resultData} /> <InfoView resultData={resultData} />
</Box> </Box>
<Box <Box
sx={{ sx={{
margin: "20px 0" margin: "20px 0",
}} }}
> >
<CustomTextField <CustomTextField
value={resultData.description} value={resultData.description}
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, (question) => question.description = target.value)} onChange={({ target }: { target: HTMLInputElement }) =>
updateQuestion(resultData.id, (question) => (question.description = target.value))
}
placeholder={"Заголовок пожирнее"} placeholder={"Заголовок пожирнее"}
sx={{ sx={{
borderRadius: "8px", borderRadius: "8px",
@ -323,9 +277,10 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
</Box> </Box>
<TextField <TextField
value={resultData.content.text} value={resultData.content.text}
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, (question) => question.content.text = target.value)} onChange={({ target }: { target: HTMLInputElement }) =>
updateQuestion(resultData.id, (question) => (question.content.text = target.value))
}
fullWidth fullWidth
placeholder="Описание" placeholder="Описание"
multiline multiline
@ -349,198 +304,77 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
}} }}
/> />
<MediaSelectionAndDisplay resultData={resultData} />
{buttonPlus ? (
<Box <Button
sx={{ onClick={() => {
mt: "20px", setButtonPlus(false);
display: "flex", }}
gap: "10px",
flexDirection: "column"
}}
>
<Box
sx={{ sx={{
display: "flex", 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 Кнопка +
sx={{ </Button>
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 <Box
sx={{ sx={{
display: "flex", mb: "30px",
flexDirection: "column",
}} }}
> >
<UploadImageModal <Box>
isOpen={isImageUploadOpen} <Typography component={"span"} sx={{ weight: "500", fontSize: "18px", mb: "10px" }}>
onClose={closeImageUploadModal} Призыв к действию
handleImageChange={handleImageUpload} </Typography>
/> <IconButton
<CropModal onClick={() => {
isOpen={isCropModalOpen} setButtonPlus(true);
imageBlob={imageBlob} updateQuestion(resultData.id, (q) => (q.content.hint.text = ""));
originalImageUrl={originalImageUrl} }}
setCropModalImageBlob={setCropModalImageBlob} >
onClose={closeCropModal} <Trash />
onSaveImageClick={handleCropModalSaveClick} </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>
)}
{
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 => {
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>
<Box <Box
sx={{ sx={{
@ -560,50 +394,42 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
> >
<MiniButtonSetting <MiniButtonSetting
onClick={() => { onClick={() => {
setResultCardSettings(!resultCardSettings) setResultCardSettings(!resultCardSettings);
}} }}
sx={{ sx={{
backgroundColor: backgroundColor: resultCardSettings ? theme.palette.brightPurple.main : "transparent",
resultCardSettings color: resultCardSettings ? "#ffffff" : theme.palette.grey3.main,
? theme.palette.brightPurple.main
: "transparent",
color:
resultCardSettings ? "#ffffff" : theme.palette.grey3.main,
"&:hover": { "&:hover": {
backgroundColor: resultCardSettings ? "#581CA7" : "#7E2AEA", backgroundColor: resultCardSettings ? "#581CA7" : "#7E2AEA",
color: "white" color: "white",
} },
}} }}
> >
<SettingIcon <SettingIcon color={resultCardSettings ? "#ffffff" : theme.palette.grey3.main} />
color={
resultCardSettings ? "#ffffff" : theme.palette.grey3.main
}
/>
{!isTablet && "Настройки"} {!isTablet && "Настройки"}
</MiniButtonSetting> </MiniButtonSetting>
</Box> </Box>
</Box> </Box>
</Box> </Box>
{ {resultCardSettings && (
resultCardSettings &&
<Box <Box
sx={{ sx={{
backgroundColor: "white", backgroundColor: "white",
p: "20px", p: "20px",
borderRadius: "0 0 12px 12px" borderRadius: "0 0 12px 12px",
}} }}
> >
<CustomTextField <CustomTextField
placeholder={"Внутреннее описание вопроса"} placeholder={"Внутреннее описание вопроса"}
value={resultData.innerName} value={resultData.innerName}
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, (question) => question.content.innerName = target.value)} onChange={({ target }: { target: HTMLInputElement }) =>
updateQuestion(resultData.id, (question) => (question.content.innerName = target.value))
}
/> />
</Box> </Box>
} )}
</> </>
) )}
} </Paper>
</Paper > );
) };
}

@ -0,0 +1,149 @@
import { FC } from "react";
import { Box, Button } from "@mui/material";
import CustomTextField from "./CustomTextField";
import { updateQuestion, uploadQuestionImage } from "@root/questions/actions";
import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal";
import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton";
import { UploadImageModal } from "../pages/Questions/UploadImage/UploadImageModal";
import { useDisclosure } from "../utils/useDisclosure";
import { useCurrentQuiz } from "../stores/quizes/hooks";
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
interface Iprops {
resultData: AnyTypedQuizQuestion;
}
export const MediaSelectionAndDisplay: FC<Iprops> = ({ resultData }) => {
const quizQid = useCurrentQuiz()?.qid;
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 (
<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) => {
q.content.video = e.target.value;
})
}
/>
</Box>
)}
</Box>
);
};