сделал нижние меню под мобилки

This commit is contained in:
ArtChaos189 2023-12-27 18:16:23 +03:00
parent db9b421066
commit d6a9955a88
8 changed files with 432 additions and 353 deletions

@ -0,0 +1,11 @@
export const BackButtonIcon = () => (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
<path
d="M7.86747 18C8.26104 18 9.9253 18 13.4337 18C17.8193 18 19 14.703 19 13.2194C19 11.7358 17.8193 8.93333 13.4337 8.93333C10.1773 8.93333 6.59726 8.93333 5 8.93333M5 8.93333L7.86747 6M5 8.93333L7.86747 11.8182"
stroke="white"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);

@ -2,14 +2,7 @@ import { FC, SVGProps } from "react";
export const CrossedEyeIcon: FC<SVGProps<SVGSVGElement>> = (props) => { export const CrossedEyeIcon: FC<SVGProps<SVGSVGElement>> = (props) => {
return ( return (
<svg <svg {...props} width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
{...props}
width="30"
height="30"
viewBox="0 0 30 30"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<rect y="0.8125" width="30" height="30" rx="6" fill="#FFF" /> <rect y="0.8125" width="30" height="30" rx="6" fill="#FFF" />
<path <path
d="M7.5 7.5625L22.5 24.0625" d="M7.5 7.5625L22.5 24.0625"

@ -1,6 +1,5 @@
import { Box, useTheme } from "@mui/material"; import { Box, useTheme } from "@mui/material";
export default function EyeIcon() { export default function EyeIcon() {
const theme = useTheme(); const theme = useTheme();
@ -15,8 +14,18 @@ export default function EyeIcon() {
}} }}
> >
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none">
<path d="M9 3.9375C3.375 3.9375 1.125 9 1.125 9C1.125 9 3.375 14.0625 9 14.0625C14.625 14.0625 16.875 9 16.875 9C16.875 9 14.625 3.9375 9 3.9375Z" stroke={theme.palette.brightPurple.main} strokeLinecap="round" strokeLinejoin="round" /> <path
<path d="M9 11.8125C10.5533 11.8125 11.8125 10.5533 11.8125 9C11.8125 7.4467 10.5533 6.1875 9 6.1875C7.4467 6.1875 6.1875 7.4467 6.1875 9C6.1875 10.5533 7.4467 11.8125 9 11.8125Z" stroke={theme.palette.brightPurple.main} strokeLinecap="round" strokeLinejoin="round" /> d="M9 3.9375C3.375 3.9375 1.125 9 1.125 9C1.125 9 3.375 14.0625 9 14.0625C14.625 14.0625 16.875 9 16.875 9C16.875 9 14.625 3.9375 9 3.9375Z"
stroke={theme.palette.brightPurple.main}
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M9 11.8125C10.5533 11.8125 11.8125 10.5533 11.8125 9C11.8125 7.4467 10.5533 6.1875 9 6.1875C7.4467 6.1875 6.1875 7.4467 6.1875 9C6.1875 10.5533 7.4467 11.8125 9 11.8125Z"
stroke={theme.palette.brightPurple.main}
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg> </svg>
</Box> </Box>
); );

@ -0,0 +1,27 @@
import { FC, SVGProps } from "react";
export const LinkSimple: FC<SVGProps<SVGSVGElement>> = (props) => (
<svg {...props} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
<path
d="M8.82031 15.1781L15.1766 8.8125"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M13.5949 16.7719L10.9418 19.425C10.5238 19.843 10.0276 20.1745 9.48151 20.4007C8.93541 20.6269 8.35009 20.7434 7.75899 20.7434C6.5652 20.7434 5.42031 20.2691 4.57618 19.425C3.73204 18.5809 3.25781 17.436 3.25781 16.2422C3.25781 15.0484 3.73204 13.9035 4.57618 13.0594L7.2293 10.4062"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M16.7719 13.5937L19.425 10.9406C20.2691 10.0965 20.7434 8.95159 20.7434 7.7578C20.7434 6.56401 20.2691 5.41912 19.425 4.57499C18.5809 3.73085 17.436 3.25662 16.2422 3.25662C15.0484 3.25662 13.9035 3.73085 13.0594 4.57499L10.4062 7.22811"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);

@ -12,21 +12,24 @@ import Page from "@icons/questionsPage/page";
import RatingIcon from "@icons/questionsPage/rating"; import RatingIcon from "@icons/questionsPage/rating";
import Slider from "@icons/questionsPage/slider"; import Slider from "@icons/questionsPage/slider";
import { import {
Box, Checkbox, Box,
Checkbox,
FormControl, FormControl,
FormControlLabel, FormControlLabel,
IconButton, IconButton,
InputAdornment, InputAdornment,
Paper, TextField, Paper,
TextField,
useMediaQuery, useMediaQuery,
useTheme useTheme,
} from "@mui/material"; } from "@mui/material";
import { import {
copyQuestion, copyQuestion,
deleteQuestion, deleteQuestionWithTimeout, deleteQuestion,
deleteQuestionWithTimeout,
toggleExpandQuestion, toggleExpandQuestion,
updateQuestion, updateQuestion,
updateUntypedQuestion updateUntypedQuestion,
} from "@root/questions/actions"; } from "@root/questions/actions";
import CustomTextField from "@ui_kit/CustomTextField"; import CustomTextField from "@ui_kit/CustomTextField";
import { useRef, useState } from "react"; import { useRef, useState } from "react";
@ -110,15 +113,13 @@ export default function QuestionsPageCard({ question, questionIndex, draggablePr
<TextField <TextField
placeholder={`Заголовок ${questionIndex + 1} вопроса`} placeholder={`Заголовок ${questionIndex + 1} вопроса`}
value={question.title} value={question.title}
onChange={({target}) => setTitle(target.value)} onChange={({ target }) => setTitle(target.value)}
sx={{ sx={{
width: "100%", width: "100%",
margin: isMobile ? "10px 0" : 0, margin: isMobile ? "10px 0" : 0,
"& .MuiInputBase-root": { "& .MuiInputBase-root": {
color: "#000000", color: "#000000",
backgroundColor: question.expanded backgroundColor: question.expanded ? theme.palette.background.default : "transparent",
? theme.palette.background.default
: "transparent",
height: "48px", height: "48px",
borderRadius: "10px", borderRadius: "10px",
".MuiOutlinedInput-notchedOutline": { ".MuiOutlinedInput-notchedOutline": {
@ -137,7 +138,7 @@ export default function QuestionsPageCard({ question, questionIndex, draggablePr
<InputAdornment <InputAdornment
ref={anchorRef} ref={anchorRef}
position="start" position="start"
sx={{cursor: "pointer"}} sx={{ cursor: "pointer" }}
onClick={() => setOpen((isOpened) => !isOpened)} onClick={() => setOpen((isOpened) => !isOpened)}
> >
{IconAndrom(question.type)} {IconAndrom(question.type)}
@ -172,7 +173,7 @@ export default function QuestionsPageCard({ question, questionIndex, draggablePr
}} }}
> >
<IconButton <IconButton
sx={{padding: "0", margin: "5px"}} sx={{ padding: "0", margin: "5px" }}
disableRipple disableRipple
data-cy="expand-question" data-cy="expand-question"
onClick={() => toggleExpandQuestion(question.id)} onClick={() => toggleExpandQuestion(question.id)}
@ -235,13 +236,8 @@ export default function QuestionsPageCard({ question, questionIndex, draggablePr
userSelect: "none", userSelect: "none",
}} }}
/> />
<IconButton <IconButton sx={{ padding: "0" }} onClick={() => copyQuestion(question.id, question.quizId)}>
sx={{ padding: "0" }} <CopyIcon style={{ color: theme.palette.brightPurple.main }} />
onClick={() => copyQuestion(question.id, question.quizId)}
>
<CopyIcon
style={{ color: theme.palette.brightPurple.main }}
/>
</IconButton> </IconButton>
<IconButton <IconButton
sx={{ sx={{
@ -252,12 +248,9 @@ export default function QuestionsPageCard({ question, questionIndex, draggablePr
}} }}
onClick={() => { onClick={() => {
deleteQuestionWithTimeout(question.id, () => deleteQuestion(question.id)); deleteQuestionWithTimeout(question.id, () => deleteQuestion(question.id));
}} }}
> >
<DeleteIcon <DeleteIcon style={{ color: theme.palette.brightPurple.main }} />
style={{ color: theme.palette.brightPurple.main }}
/>
</IconButton> </IconButton>
</Box> </Box>
)} )}
@ -289,16 +282,16 @@ export default function QuestionsPageCard({ question, questionIndex, draggablePr
}} }}
{...draggableProps} {...draggableProps}
> >
<PointsIcon style={{color: "#4D4D4D", fontSize: "30px"}}/> <PointsIcon style={{ color: "#4D4D4D", fontSize: "30px" }} />
</IconButton> </IconButton>
</Box> </Box>
</Box> </Box>
{question.expanded && ( {question.expanded && (
<> <>
{question.type === null ? ( {question.type === null ? (
<FormTypeQuestions question={question}/> <FormTypeQuestions question={question} />
) : ( ) : (
<SwitchQuestionsPage question={question}/> <SwitchQuestionsPage question={question} />
)} )}
</> </>
)} )}

@ -4,6 +4,8 @@ import BackArrowIcon from "@icons/BackArrowIcon";
import { Burger } from "@icons/Burger"; import { Burger } from "@icons/Burger";
import EyeIcon from "@icons/EyeIcon"; import EyeIcon from "@icons/EyeIcon";
import { PenaLogoIcon } from "@icons/PenaLogoIcon"; import { PenaLogoIcon } from "@icons/PenaLogoIcon";
import VisibilityIcon from "@mui/icons-material/Visibility";
import { import {
Box, Box,
Button, Button,
@ -54,6 +56,9 @@ import { ModalInfoWhyCantCreate } from "./ModalInfoWhyCantCreate";
import { ConfirmLeaveModal } from "./ConfirmLeaveModal"; import { ConfirmLeaveModal } from "./ConfirmLeaveModal";
import { checkQuestionHint } from "@utils/checkQuestionHint"; import { checkQuestionHint } from "@utils/checkQuestionHint";
import { deleteTimeoutedQuestions } from "@utils/deleteTimeoutedQuestions"; import { deleteTimeoutedQuestions } from "@utils/deleteTimeoutedQuestions";
import { toggleQuizPreview } from "@root/quizPreview";
import { LinkSimple } from "@icons/LinkSimple";
import { BackButtonIcon } from "@icons/BackButtonIcon";
let init: () => void; let init: () => void;
export default function EditPage() { export default function EditPage() {
@ -93,6 +98,7 @@ export default function EditPage() {
const currentStep = useQuizStore((state) => state.currentStep); const currentStep = useQuizStore((state) => state.currentStep);
const isTablet = useMediaQuery(theme.breakpoints.down(1000)); const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const isMobile = useMediaQuery(theme.breakpoints.down(660)); const isMobile = useMediaQuery(theme.breakpoints.down(660));
const isMobileSm = useMediaQuery(theme.breakpoints.down(370));
const [mobileSidebar, setMobileSidebar] = useState<boolean>(false); const [mobileSidebar, setMobileSidebar] = useState<boolean>(false);
const [nextStep, setNextStep] = useState<number>(0); const [nextStep, setNextStep] = useState<number>(0);
const quizConfig = quiz?.config; const quizConfig = quiz?.config;
@ -156,6 +162,27 @@ export default function EditPage() {
if (!quizConfig) return <></>; if (!quizConfig) return <></>;
const isConditionMet = [1].includes(currentStep) && !openBranchingPanel && quizConfig.type !== "form"; const isConditionMet = [1].includes(currentStep) && !openBranchingPanel && quizConfig.type !== "form";
const [buttonText, setButtonText] = useState("Опубликовать");
const handleClickStatusQuiz = () => {
if (Object.keys(whyCantCreatePublic).length === 0) {
setButtonText("Опубликовано");
setTimeout(() => {
setButtonText("Отозвать");
}, 3000);
updateQuiz(quiz?.id, (state) => {
state.status = quiz?.status === "start" ? "stop" : "start";
});
} else {
updateModalInfoWhyCantCreate(true);
}
};
console.log(buttonText);
return ( return (
<> <>
{/*хедер*/} {/*хедер*/}
@ -289,14 +316,14 @@ export default function EditPage() {
sx={{ sx={{
background: theme.palette.background.default, background: theme.palette.background.default,
width: "100%", width: "100%",
overflow: "hidden",
}} }}
> >
<Box <Box
sx={{ sx={{
padding: isMobile ? "16px 16px 20px 16px" : "25px 25px 20px 25px", padding: isMobile ? "16px 16px 20px 16px" : "25px 25px 20px 25px",
overflow: "auto", overflow: "auto",
height: `calc(100vh - ${isConditionMet ? "186px" : "156px"})`, height: isMobile ? ` calc(100vh - 125px) ` : `calc(100vh - ${isConditionMet ? "186px" : "166px"})`,
boxSizing: "border-box", boxSizing: "border-box",
}} }}
> >
@ -320,7 +347,8 @@ export default function EditPage() {
width: "100%", width: "100%",
padding: isMobile ? "20px 16px" : "20px 20px", padding: isMobile ? "20px 16px" : "20px 20px",
display: "flex", display: "flex",
justifyContent: "flex-start", justifyContent: isMobile ? (isMobileSm ? "center" : "flex-end") : "flex-start",
flexDirection: isMobile ? "row-reverse" : "-moz-initial",
alignItems: "center", alignItems: "center",
gap: "15px", gap: "15px",
background: "#FFF", background: "#FFF",
@ -387,6 +415,7 @@ export default function EditPage() {
</Box> </Box>
)} )}
<Box sx={{ display: isMobile ? "none" : "block" }}>
{!canCreatePublic && quiz.config.type !== "form" ? ( {!canCreatePublic && quiz.config.type !== "form" ? (
<Button <Button
variant="contained" variant="contained"
@ -418,33 +447,32 @@ export default function EditPage() {
</Button> </Button>
</a> </a>
)} )}
</Box>
<Button <Button
variant="outlined" variant="contained"
sx={{ sx={{
fontSize: "14px", fontSize: "14px",
lineHeight: "18px", lineHeight: "18px",
height: "34px", height: "34px",
border: `1px solid ${theme.palette.brightPurple.main}`, background: buttonText === "Опубликовать" || "Отозвать" ? "#7E2AEA" : "#FA5B0E",
backgroundColor: quiz?.status === "start" ? theme.palette.brightPurple.main : "transparent",
color: quiz?.status === "start" ? "#FFFFFF" : theme.palette.brightPurple.main,
}} }}
onClick={ onClick={handleClickStatusQuiz}
Object.keys(whyCantCreatePublic).length === 0
? () =>
updateQuiz(quiz?.id, (state) => {
state.status = quiz?.status === "start" ? "stop" : "start";
})
: () => updateModalInfoWhyCantCreate(true)
}
> >
{quiz?.status === "start" ? "Стоп" : "Старт"} {buttonText === "Отозвать" ? (
<Box sx={{ display: "flex", gap: "4px", alignItems: "center" }}>
{buttonText} <BackButtonIcon />
</Box>
) : (
buttonText
)}
</Button> </Button>
{quiz?.status === "start" && ( {quiz?.status === "start" && (
<Box <Box
component={Link} component={Link}
sx={{ sx={{
color: "#7e2aea", display: isMobile ? "none" : "block",
color: "#7E2AEA",
fontSize: "14px", fontSize: "14px",
}} }}
target="_blank" target="_blank"
@ -453,6 +481,61 @@ export default function EditPage() {
https://hbpn.link/{quiz.qid} https://hbpn.link/{quiz.qid}
</Box> </Box>
)} )}
{isMobile ? (
<Button
onClick={toggleQuizPreview}
variant="outlined"
sx={{
display: "flex",
gap: "4px",
fontSize: "14px",
lineHeight: "18px",
height: "34px",
border: "1px solid #7E2AEA",
color: "#7E2AEA",
background: "white",
p: "8px 14px",
}}
>
<EyeIcon />
Предпросмотр
</Button>
) : (
<IconButton
onClick={toggleQuizPreview}
sx={{
pointerEvents: "auto",
marginLeft: "auto",
position: "relative",
zIndex: "999999",
}}
>
<VisibilityIcon sx={{ height: "30px", width: "30px" }} />
</IconButton>
)}
{isMobile && quiz?.status === "start" && (
<Box
component={Link}
sx={{
cursor: "pointer",
width: "34px",
height: "34px",
color: "#7E2AEA",
fontSize: "14px",
display: "flex",
justifyContent: "center",
alignItems: "Center",
background: "#EEE4FC",
borderRadius: "8px",
}}
target="_blank"
to={"https://hbpn.link/" + quiz.qid}
>
<LinkSimple />
</Box>
)}
</Box> </Box>
</Box> </Box>
</Box> </Box>

@ -1,4 +1,3 @@
import VisibilityIcon from '@mui/icons-material/Visibility';
import { Box, IconButton } from "@mui/material"; import { Box, IconButton } from "@mui/material";
import { toggleQuizPreview, useQuizPreviewStore } from "@root/quizPreview"; import { toggleQuizPreview, useQuizPreviewStore } from "@root/quizPreview";
import { useLayoutEffect, useRef } from "react"; import { useLayoutEffect, useRef } from "react";
@ -34,13 +33,7 @@ export default function QuizPreview() {
function stickPreviewToBottomRight() { function stickPreviewToBottomRight() {
const rnd = rndRef.current; const rnd = rndRef.current;
const rndSelfElement = rnd?.getSelfElement(); const rndSelfElement = rnd?.getSelfElement();
if ( if (!rnd || !rndSelfElement || !rndParentRef.current || !isFirstShowRef.current) return;
!rnd ||
!rndSelfElement ||
!rndParentRef.current ||
!isFirstShowRef.current
)
return;
const rndParentRect = rndParentRef.current.getBoundingClientRect(); const rndParentRect = rndParentRef.current.getBoundingClientRect();
const rndRect = rndSelfElement.getBoundingClientRect(); const rndRect = rndSelfElement.getBoundingClientRect();
@ -118,18 +111,6 @@ export default function QuizPreview() {
<QuizPreviewLayout /> <QuizPreviewLayout />
</Rnd> </Rnd>
)} )}
<IconButton
onClick={toggleQuizPreview}
data-cy="toggle-quiz-preview"
sx={{
position: "absolute",
right: 0,
bottom: 0,
pointerEvents: "auto",
}}
>
<VisibilityIcon sx={{ height: "30px", width: "30px" }} />
</IconButton>
</Box> </Box>
); );
} }

@ -1,4 +1,3 @@
import VisibilityIcon from "@mui/icons-material/Visibility";
import { Box, IconButton, useTheme, useMediaQuery } from "@mui/material"; import { Box, IconButton, useTheme, useMediaQuery } from "@mui/material";
import { toggleQuizPreview, useQuizPreviewStore } from "@root/quizPreview"; import { toggleQuizPreview, useQuizPreviewStore } from "@root/quizPreview";
import { useLayoutEffect, useRef } from "react"; import { useLayoutEffect, useRef } from "react";
@ -35,13 +34,7 @@ export const StartPagePreview = () => {
function stickPreviewToBottomRight() { function stickPreviewToBottomRight() {
const rnd = rndRef.current; const rnd = rndRef.current;
const rndSelfElement = rnd?.getSelfElement(); const rndSelfElement = rnd?.getSelfElement();
if ( if (!rnd || !rndSelfElement || !rndParentRef.current || !isFirstShowRef.current) return;
!rnd ||
!rndSelfElement ||
!rndParentRef.current ||
!isFirstShowRef.current
)
return;
const rndParentRect = rndParentRef.current.getBoundingClientRect(); const rndParentRect = rndParentRef.current.getBoundingClientRect();
const rndRect = rndSelfElement.getBoundingClientRect(); const rndRect = rndSelfElement.getBoundingClientRect();
@ -119,17 +112,6 @@ export const StartPagePreview = () => {
<QuizPreviewLayout /> <QuizPreviewLayout />
</Rnd> </Rnd>
)} )}
<IconButton
onClick={toggleQuizPreview}
sx={{
position: "absolute",
right: 0,
bottom: 0,
pointerEvents: "auto",
}}
>
<VisibilityIcon sx={{ height: "30px", width: "30px" }} />
</IconButton>
</Box> </Box>
); );
}; };