diff --git a/src/assets/icons/ResizeIcon.tsx b/src/assets/icons/ResizeIcon.tsx new file mode 100644 index 00000000..daeb81c6 --- /dev/null +++ b/src/assets/icons/ResizeIcon.tsx @@ -0,0 +1,35 @@ +import { Box, SxProps, Theme } from "@mui/material"; + +interface Props { + sx?: SxProps; +} + +export default function ResizeIcon({ sx }: Props) { + return ( + + + + + + ); +} diff --git a/src/pages/startPage/StartPageSettings.tsx b/src/pages/startPage/StartPageSettings.tsx index 75c14baa..cd4b47c7 100755 --- a/src/pages/startPage/StartPageSettings.tsx +++ b/src/pages/startPage/StartPageSettings.tsx @@ -1,3 +1,4 @@ +import { ChangeEvent, useState } from "react"; import { Box, Button, @@ -12,7 +13,7 @@ import { useMediaQuery, useTheme, } from "@mui/material"; -import { ChangeEvent, useState } from "react"; +import { createPortal } from "react-dom"; import CustomCheckbox from "@ui_kit/CustomCheckbox"; import AlignLeftIcon from "@icons/AlignLeftIcon"; import AlignRightIcon from "@icons/AlignRightIcon"; @@ -31,11 +32,12 @@ import { quizStore } from "@root/quizes"; import { useParams } from "react-router-dom"; import * as React from "react"; import ModalSizeImage from "./ModalSizeImage"; -import DropZone from "./dropZone"; +import { DropZone } from "./dropZone"; import Extra from "./extra"; import AlignCenterIcon from "@icons/AlignCenterIcon"; import DropFav from "./dropfavicon"; import { createQuestion } from "@root/questions"; +import { StartPagePreview } from "@ui_kit/StartPagePreview"; const designTypes = [ [ @@ -906,6 +908,7 @@ export default function StartPageSettings() { Настроить вопросы + {createPortal(, document.body)} ); } diff --git a/src/pages/startPage/dropZone.tsx b/src/pages/startPage/dropZone.tsx index d354b077..a9036853 100644 --- a/src/pages/startPage/dropZone.tsx +++ b/src/pages/startPage/dropZone.tsx @@ -1,8 +1,19 @@ import { useState } from "react"; -import { Box, ButtonBase, useTheme, Typography, SxProps, Theme } from "@mui/material"; -import UploadIcon from "../../assets/icons/UploadIcon"; +import { useParams } from "react-router-dom"; +import { + Box, + ButtonBase, + useTheme, + Typography, + SxProps, + Theme, +} from "@mui/material"; import { SnackbarProvider, enqueueSnackbar } from "notistack"; +import { quizStore } from "@root/quizes"; + +import UploadIcon from "@icons/UploadIcon"; + interface Props { text?: string; sx?: SxProps; @@ -11,21 +22,35 @@ interface Props { } //Научи функцию принимать данные для валидации -export default ({ text, sx, heightImg, widthImg }: Props) => { +export const DropZone = ({ text, sx, heightImg, widthImg }: Props) => { + const quizId = Number(useParams().quizId); + const { listQuizes, updateQuizesList } = quizStore(); + const [ready, setReady] = useState(false); const theme = useTheme(); + const quiz = listQuizes[quizId]; + console.log(quiz.config.startpage.background.desktop); const imgHC = (imgInp: HTMLInputElement) => { const file = imgInp.files?.[0]; if (file) { if (file.size < 5242880) { - setData(URL.createObjectURL(file)); + updateQuizesList(quizId, { + config: { + ...quiz.config, + startpage: { + ...quiz.config.startpage, + background: { + ...quiz.config.startpage.background, + desktop: URL.createObjectURL(file), + }, + }, + }, + }); } else { enqueueSnackbar("Размер картинки слишком велик"); } } }; - const [data, setData] = useState(""); - const [ready, setReady] = useState(false); const dragenterHC = () => { setReady(true); @@ -41,7 +66,18 @@ export default ({ text, sx, heightImg, widthImg }: Props) => { const file = event.dataTransfer.files[0]; if (file.size < 5242880) { - setData(URL.createObjectURL(file)); + updateQuizesList(quizId, { + config: { + ...quiz.config, + startpage: { + ...quiz.config.startpage, + background: { + ...quiz.config.startpage.background, + desktop: URL.createObjectURL(file), + }, + }, + }, + }); } else { enqueueSnackbar("Размер картинки слишком велик"); } @@ -53,7 +89,13 @@ export default ({ text, sx, heightImg, widthImg }: Props) => { return ( - imgHC(event.target)} hidden accept="image/*" multiple type="file" /> + imgHC(event.target)} + hidden + accept="image/*" + multiple + type="file" + /> { backgroundColor: theme.palette.background.default, border: `1px solid ${ready ? "red" : theme.palette.grey2.main}`, borderRadius: "8px", - opacity: data ? "0.5" : 1, + opacity: quiz.config.startpage.background.desktop ? "0.5" : 1, ...sx, }} > @@ -87,19 +129,22 @@ export default ({ text, sx, heightImg, widthImg }: Props) => { > {text} - - {data ? ( + + {quiz.config.startpage.background.desktop && ( img - ) : null} + )} ); diff --git a/src/stores/quizes.ts b/src/stores/quizes.ts index 152702fd..40246bef 100644 --- a/src/stores/quizes.ts +++ b/src/stores/quizes.ts @@ -133,9 +133,9 @@ export const quizStore = create()( "position": "ltr", // ltr или rtl. отображение элементов поверх фона "background": { "type": "image", //image или video - "desktop": "hub.pena.digital/img/back/full.png", - "mobile": "hub.pena.digital/img/back/mobile.png", - "video":"hub.pena.digital/vid/back/vi1.mp4", + "desktop": "", + "mobile": "", + "video":"", "cycle": true //зацикливать видео или нет }, }, diff --git a/src/ui_kit/QuizPreview/QuizPreview.tsx b/src/ui_kit/QuizPreview/QuizPreview.tsx index e7f8e942..00d0a04f 100644 --- a/src/ui_kit/QuizPreview/QuizPreview.tsx +++ b/src/ui_kit/QuizPreview/QuizPreview.tsx @@ -5,7 +5,7 @@ import { useLayoutEffect, useRef } from "react"; import { Rnd } from "react-rnd"; import { useWindowSize } from "../../utils/hooks/useWindowSize"; import QuizPreviewLayout from "./QuizPreviewLayout"; -import ResizeIcon from "./ResizeIcon"; +import ResizeIcon from "@icons/ResizeIcon"; const DRAG_PARENT_MARGIN = 0; const NAVBAR_HEIGHT = 0; diff --git a/src/ui_kit/QuizPreview/ResizeIcon.tsx b/src/ui_kit/QuizPreview/ResizeIcon.tsx deleted file mode 100644 index 3d5895d6..00000000 --- a/src/ui_kit/QuizPreview/ResizeIcon.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Box, SxProps, Theme } from "@mui/material"; - - -interface Props { - sx?: SxProps; -} - -export default function ResizeIcon({ sx }: Props) { - - return ( - - - - - - ); -} diff --git a/src/ui_kit/StartPagePreview/QuizPreviewLayout.tsx b/src/ui_kit/StartPagePreview/QuizPreviewLayout.tsx new file mode 100644 index 00000000..d3cd60ea --- /dev/null +++ b/src/ui_kit/StartPagePreview/QuizPreviewLayout.tsx @@ -0,0 +1,139 @@ +import { + Box, + Button, + Paper, + Typography, + useTheme, + useMediaQuery, +} from "@mui/material"; +import { useParams } from "react-router-dom"; + +import { quizStore } from "@root/quizes"; + +export default function QuizPreviewLayout() { + const quizId = Number(useParams().quizId); + const { listQuizes } = quizStore(); + const question = listQuizes[quizId]; + const theme = useTheme(); + const isTablet = useMediaQuery(theme.breakpoints.down(630)); + const isMediaFileExist = + (question.config.startpage.background.type === "image" && + question.config.startpage.background.desktop) || + (question.config.startpage.background.type === "video" && + question.config.startpage.background.video); + + return ( + + + + + {question.config.startpage.background.type === "image" && + question.config.startpage.background.desktop && ( + + )} + + {question.config.info.orgname} + + + + {question.name} + + {question.config.startpage.description} + + + {question.config.startpage.button && ( + + )} + + + + + {question.config.info.phonenumber} + + + {question.config.info.law} + + + + {!isTablet && isMediaFileExist && ( + + {question.config.startpage.background.type === "image" && + question.config.startpage.background.desktop && ( + + )} + {question.config.startpage.background.type === "video" && + question.config.startpage.background.video && ( + + )} + + + ); +} diff --git a/src/ui_kit/StartPagePreview/index.tsx b/src/ui_kit/StartPagePreview/index.tsx new file mode 100644 index 00000000..17c0c23f --- /dev/null +++ b/src/ui_kit/StartPagePreview/index.tsx @@ -0,0 +1,134 @@ +import VisibilityIcon from "@mui/icons-material/Visibility"; +import { Box, IconButton, useTheme, useMediaQuery } from "@mui/material"; +import { toggleQuizPreview, useQuizPreviewStore } from "@root/quizPreview"; +import { useLayoutEffect, useRef } from "react"; +import { Rnd } from "react-rnd"; +import QuizPreviewLayout from "./QuizPreviewLayout"; +import ResizeIcon from "@icons/ResizeIcon"; + +const DRAG_PARENT_MARGIN = 0; +const NAVBAR_HEIGHT = 0; +const DRAG_PARENT_BOTTOM_MARGIN = 0; + +interface RndPositionAndSize { + x: number; + y: number; + width: string; + height: string; +} + +export const StartPagePreview = () => { + const isPreviewShown = useQuizPreviewStore((state) => state.isPreviewShown); + const rndParentRef = useRef(null); + const rndRef = useRef(null); + const theme = useTheme(); + const isTablet = useMediaQuery(theme.breakpoints.down(630)); + const rndPositionAndSizeRef = useRef({ + x: 0, + y: 0, + width: isTablet ? "350" : "600", + height: "330", + }); + const isFirstShowRef = useRef(true); + + useLayoutEffect( + function stickPreviewToBottomRight() { + const rnd = rndRef.current; + const rndSelfElement = rnd?.getSelfElement(); + if ( + !rnd || + !rndSelfElement || + !rndParentRef.current || + !isFirstShowRef.current + ) + return; + + const rndParentRect = rndParentRef.current.getBoundingClientRect(); + const rndRect = rndSelfElement.getBoundingClientRect(); + + const x = rndParentRect.width - rndRect.width; + const y = rndParentRect.height - rndRect.height; + + rnd.updatePosition({ x, y }); + rndPositionAndSizeRef.current.x = x; + rndPositionAndSizeRef.current.y = y; + + isFirstShowRef.current = false; + }, + [isPreviewShown] + ); + + return ( + + {isPreviewShown && ( + { + rndPositionAndSizeRef.current.x = position.x; + rndPositionAndSizeRef.current.y = position.y; + rndPositionAndSizeRef.current.width = ref.style.width; + rndPositionAndSizeRef.current.height = ref.style.height; + }} + onDragStop={(e, d) => { + rndPositionAndSizeRef.current.x = d.x; + rndPositionAndSizeRef.current.y = d.y; + }} + onDragStart={(e, d) => { + e.preventDefault(); + }} + enableResizing={{ + topLeft: isPreviewShown, + }} + resizeHandleComponent={{ + topLeft: , + }} + resizeHandleStyles={{ + topLeft: { + top: "-1px", + left: "-1px", + }, + }} + style={{ + overflow: "hidden", + pointerEvents: "auto", + borderRadius: "5px", + }} + > + + + )} + + + + + ); +};