diff --git a/src/pages/Questions/PageOptions/PageOptions.tsx b/src/pages/Questions/PageOptions/PageOptions.tsx index b7878072..a9ccf035 100644 --- a/src/pages/Questions/PageOptions/PageOptions.tsx +++ b/src/pages/Questions/PageOptions/PageOptions.tsx @@ -1,18 +1,13 @@ -import { VideofileIcon } from "@icons/questionsPage/VideofileIcon"; -import { Box, Button, Typography, useMediaQuery, useTheme } from "@mui/material"; -import { updateQuestion, uploadQuestionImage } from "@root/questions/actions"; -import { useCurrentQuiz } from "@root/quizes/hooks"; -import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton"; +import { Box, useMediaQuery, useTheme } from "@mui/material"; +import { updateQuestion } from "@root/questions/actions"; import CustomTextField from "@ui_kit/CustomTextField"; -import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal"; + import { useState } from "react"; import { useDebouncedCallback } from "use-debounce"; import type { QuizQuestionPage } from "../../../model/questionTypes/page"; import ButtonsOptions from "../ButtonsOptions"; -import { UploadImageModal } from "../UploadImage/UploadImageModal"; -import { UploadVideoModal } from "../UploadVideoModal"; import SwitchPageOptions from "./switchPageOptions"; -import { useDisclosure } from "../../../utils/useDisclosure"; +import { MediaSelectionAndDisplay } from "@ui_kit/MediaSelectionAndDisplay"; type Props = { disableInput?: boolean; @@ -20,16 +15,11 @@ type Props = { }; export default function PageOptions({ disableInput, question }: Props) { - const [openVideoModal, setOpenVideoModal] = useState(false); const [switchState, setSwitchState] = useState("setting"); const theme = useTheme(); const isTablet = useMediaQuery(theme.breakpoints.down(980)); const isFigmaTablet = useMediaQuery(theme.breakpoints.down(990)); 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) => { updateQuestion(question.id, (question) => { @@ -43,27 +33,6 @@ export default function PageOptions({ disableInput, question }: Props) { 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 ( <> @@ -84,179 +52,7 @@ export default function PageOptions({ disableInput, question }: Props) { /> - - - { - if (question.content.picture) { - return openCropModal(question.content.picture, question.content.originalPicture); - } - - openImageUploadModal(); - }} - onPlusClick={() => { - openImageUploadModal(); - }} - /> - - - updateQuestion(question.id, (question) => ((question as QuizQuestionPage).content.useImage = true)) - } - > - Изображение - - - - - или - - {isMobile ? ( - - - - - - + - - - ) : ( - - - - - setOpenVideoModal(true)} - style={{ - display: "flex", - alignItems: "center", - justifyContent: "center", - background: "#7E2AEA", - height: "100%", - width: "25px", - color: "white", - fontSize: "15px", - }} - > - + - - - )} - - - updateQuestion(question.id, (question) => ((question as QuizQuestionPage).content.useImage = false)) - } - > - Видео - - - setOpenVideoModal(false)} - video={question.content.video} - onUpload={(url) => { - updateQuestion(question.id, (question) => { - if (question.type !== "page") return; - - question.content.video = url; - }); - }} - /> - + diff --git a/src/pages/ResultPage/cards/ResultCard.tsx b/src/pages/ResultPage/cards/ResultCard.tsx index 5c92de35..404b92a5 100644 --- a/src/pages/ResultPage/cards/ResultCard.tsx +++ b/src/pages/ResultPage/cards/ResultCard.tsx @@ -1,14 +1,8 @@ import * as React from "react"; -import { getQuestionByContentId, updateQuestion, uploadQuestionImage } from "@root/questions/actions" -import { useCurrentQuiz } from "@root/quizes/hooks" - +import { getQuestionByContentId, updateQuestion } from "@root/questions/actions"; 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, @@ -20,7 +14,7 @@ import { useMediaQuery, useTheme, FormControl, - Popover + Popover, } from "@mui/material"; import MiniButtonSetting from "@ui_kit/MiniButtonSetting"; @@ -30,7 +24,7 @@ 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"; +import { MediaSelectionAndDisplay } from "@ui_kit/MediaSelectionAndDisplay"; interface Props { resultContract: boolean; @@ -38,7 +32,7 @@ interface Props { } export const checkEmptyData = ({ resultData }: { resultData: QuizQuestionResult }) => { - let check = true + let check = true; if ( resultData.title.length > 0 || resultData.description.length > 0 || @@ -47,14 +41,15 @@ export const checkEmptyData = ({ resultData }: { resultData: QuizQuestionResult 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 -} + 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 checkEmpty = checkEmptyData({ resultData }); + const question = getQuestionByContentId(resultData.content.rule.parentId); const [anchorEl, setAnchorEl] = React.useState(null); const handleClick = (event: React.MouseEvent) => { @@ -66,20 +61,18 @@ const InfoView = ({ resultData }: { resultData: QuizQuestionResult }) => { }; const open = Boolean(anchorEl); - const id = open ? 'simple-popover' : undefined; + const id = open ? "simple-popover" : undefined; return ( <> { anchorEl={anchorEl} onClose={handleClose} anchorOrigin={{ - vertical: 'bottom', - horizontal: 'left', + vertical: "bottom", + horizontal: "left", }} > - {resultData?.content.rule.parentId === "line" ? "Единый результат в конце прохождения опросника без ветвления" - : - `Заголовок вопроса, после которого появится результат: "${question?.title || "нет заголовка"}"` - } - + {resultData?.content.rule.parentId === "line" + ? "Единый результат в конце прохождения опросника без ветвления" + : `Заголовок вопроса, после которого появится результат: "${question?.title || "нет заголовка"}"`} - {checkEmpty && - - Вы не заполнили этот результат никакими данными - - } - + {checkEmpty && Вы не заполнили этот результат никакими данными} - ) -} + ); +}; export const ResultCard = ({ resultContract, resultData }: Props) => { - - 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) + 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; - }); - } - - - + setExpand(true); + }, [resultContract]); return ( { backgroundColor: expand ? "white" : "#EEE4FC", border: expand ? "none" : "1px solid #9A9AAF", boxShadow: "0px 10px 30px #e7e7e7", - m: "20px 0" + m: "20px 0", }} > { flexDirection: isMobile ? "column" : null, justifyContent: "space-between", minHeight: "40px", - }} > { updateQuestion(resultData.id, question => question.title = target.value)} + 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", + backgroundColor: expand ? theme.palette.background.default : "transparent", height: "48px", borderRadius: "10px", ".MuiOutlinedInput-notchedOutline": { @@ -291,7 +242,10 @@ export const ResultCard = ({ resultContract, resultData }: Props) => { updateQuestion(resultData.id, question => question.title = target.value)} /> + onChange={({ target }: { target: HTMLInputElement }) => + updateQuestion(resultData.id, (question) => (question.title = target.value)) + } + /> { - - updateQuestion(resultData.id, (question) => question.description = target.value)} + onChange={({ target }: { target: HTMLInputElement }) => + updateQuestion(resultData.id, (question) => (question.description = target.value)) + } placeholder={"Заголовок пожирнее"} sx={{ borderRadius: "8px", @@ -323,9 +277,10 @@ export const ResultCard = ({ resultContract, resultData }: Props) => { updateQuestion(resultData.id, (question) => question.content.text = target.value)} + onChange={({ target }: { target: HTMLInputElement }) => + updateQuestion(resultData.id, (question) => (question.content.text = target.value)) + } fullWidth placeholder="Описание" multiline @@ -349,198 +304,77 @@ export const ResultCard = ({ resultContract, resultData }: Props) => { }} /> + - - - { + setButtonPlus(false); + }} 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", }} > - - - - + Кнопка + + + ) : ( - - + + Призыв к действию + + { + setButtonPlus(true); + updateQuestion(resultData.id, (q) => (q.content.hint.text = "")); + }} + > + + + + + + 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, + }, + }} /> - - { - resultData.content.useImage && - - { - if (resultData.content.back) { - return openCropModal( - resultData.content.back, - resultData.content.originalBack - ); - } - - openImageUploadModal(); - }} - onPlusClick={() => { - openImageUploadModal(); - }} - /> - - } - { - !resultData.content.useImage && - - updateQuestion(resultData.id, q => { - q.content.video = e.target.value; - })} - /> - - } - - - - - { - buttonPlus ? - - : - - - - Призыв к действию - - { - setButtonPlus(true) - updateQuestion(resultData.id, (q) => q.content.hint.text = "") - }} - > - - - - - 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, - }, - }} - /> - - } - - - - - - - + )} { > { - setResultCardSettings(!resultCardSettings) + setResultCardSettings(!resultCardSettings); }} sx={{ - backgroundColor: - resultCardSettings - ? theme.palette.brightPurple.main - : "transparent", - color: - resultCardSettings ? "#ffffff" : theme.palette.grey3.main, + backgroundColor: resultCardSettings ? theme.palette.brightPurple.main : "transparent", + color: resultCardSettings ? "#ffffff" : theme.palette.grey3.main, "&:hover": { backgroundColor: resultCardSettings ? "#581CA7" : "#7E2AEA", - color: "white" - } + color: "white", + }, }} > - + {!isTablet && "Настройки"} - { - resultCardSettings && + {resultCardSettings && ( updateQuestion(resultData.id, (question) => question.content.innerName = target.value)} + onChange={({ target }: { target: HTMLInputElement }) => + updateQuestion(resultData.id, (question) => (question.content.innerName = target.value)) + } /> - } + )} - ) - } - - ) -} + )} + + ); +}; diff --git a/src/ui_kit/MediaSelectionAndDisplay.tsx b/src/ui_kit/MediaSelectionAndDisplay.tsx new file mode 100644 index 00000000..88a47ac4 --- /dev/null +++ b/src/ui_kit/MediaSelectionAndDisplay.tsx @@ -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 = ({ 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 ( + + + + + + + + + + + + {resultData.content.useImage && ( + + { + if (resultData.content.back) { + return openCropModal(resultData.content.back, resultData.content.originalBack); + } + + openImageUploadModal(); + }} + onPlusClick={() => { + openImageUploadModal(); + }} + /> + + )} + {!resultData.content.useImage && ( + + + updateQuestion(resultData.id, (q) => { + q.content.video = e.target.value; + }) + } + /> + + )} + + ); +};