мобильная версия публикации вопросов

This commit is contained in:
Tamara 2023-12-27 21:52:05 +03:00
parent ee87a5d7a8
commit 520a36423f
8 changed files with 245 additions and 129 deletions

@ -1,5 +1,5 @@
import { useState, useEffect } from "react";
import { Box, Button, Typography, useTheme } from "@mui/material";
import {Box, Button, Typography, useMediaQuery, useTheme} from "@mui/material";
import { useQuizViewStore } from "@root/quizView";
import { useCurrentQuiz } from "@root/quizes/hooks";
@ -29,6 +29,7 @@ export const Footer = ({ setCurrentQuestion, question, setShowContactForm, setSh
const { answers } = useQuizViewStore();
const questions = useQuestionsStore().questions as AnyTypedQuizQuestion[];
const theme = useTheme();
const isMobileMini = useMediaQuery(theme.breakpoints.down(382));
const linear = !questions.find(({ content }) => content.rule.parentId === "root");
useEffect(() => {
@ -236,13 +237,11 @@ export const Footer = ({ setCurrentQuestion, question, setShowContactForm, setSh
gap: "10px",
}}
>
{mode[quiz.config.theme] ? (
<NameplateLogoFQ style={{ fontSize: "34px", width:"200px", height:"auto" }} />
):(
<NameplateLogoFQDark style={{ fontSize: "34px", width:"200px", height:"auto" }} />
)
}
{/*{mode[quiz.config.theme] ? (*/}
{/* <NameplateLogoFQ style={{ fontSize: "34px", width:"200px", height:"auto" }} />*/}
{/*):(*/}
{/* <NameplateLogoFQDark style={{ fontSize: "34px", width:"200px", height:"auto" }} />*/}
{/*)}*/}
{linear &&
<>
<Box
@ -251,7 +250,7 @@ export const Footer = ({ setCurrentQuestion, question, setShowContactForm, setSh
alignItems: "center",
gap: "10px",
marginRight: "auto",
color: theme.palette.grey1.main,
color: theme.palette.text.primary,
}}
>
<Typography>Шаг</Typography>
@ -265,7 +264,7 @@ export const Footer = ({ setCurrentQuestion, question, setShowContactForm, setSh
width: "30px",
height: "30px",
color: "#FFF",
background: theme.palette.brightPurple.main,
background: theme.palette.primary.main,
}}
>
{stepNumber}
@ -311,10 +310,16 @@ export const Footer = ({ setCurrentQuestion, question, setShowContactForm, setSh
<Button
disabled={disablePreviousButton}
variant="contained"
sx={{ fontSize: "16px", padding: "10px 15px", "& :disabled": {color: `{hsl((theme.palette.primary.main) 30%)}`} }}
sx={{ fontSize: "16px", padding: "10px 15px",}}
onClick={followPreviousStep}
>
Назад
{isMobileMini ? (
"←"
) : (
"← Назад"
)}
</Button>
<Button
disabled={disableNextButton}

@ -22,6 +22,9 @@ import { ResultQuestion } from "./ResultQuestion";
import type { QuestionType } from "../../model/question/question";
import type { AnyTypedQuizQuestion } from "../../model/questionTypes/shared";
import {NameplateLogoFQ} from "@icons/NameplateLogoFQ";
import {NameplateLogoFQDark} from "@icons/NameplateLogoFQDark";
import {modes} from "@utils/themes/Publication/themePublication";
type QuestionProps = {
questions: AnyTypedQuizQuestion[];
@ -46,7 +49,7 @@ export const Question = ({ questions }: QuestionProps) => {
const [currentQuestion, setCurrentQuestion] = useState<AnyTypedQuizQuestion>();
const [showContactForm, setShowContactForm] = useState<boolean>(false);
const [showResultForm, setShowResultForm] = useState<boolean>(false);
const mode = modes;
useEffect(() => {
const nextQuestion = getQuestionByContentId(quiz?.config.haveRoot || "");
@ -80,9 +83,18 @@ export const Question = ({ questions }: QuestionProps) => {
maxWidth: "1440px",
padding: "40px 25px 20px",
margin: "0 auto",
overflow: "auto",
display: "flex",
flexDirection: "column",
justifyContent: "space-between"
}}
>
<QuestionComponent currentQuestion={currentQuestion} />
{mode[quiz.config.theme] ? (
<NameplateLogoFQ style={{ fontSize: "34px", width:"200px", height:"auto" }} />
):(
<NameplateLogoFQDark style={{ fontSize: "34px", width:"200px", height:"auto" }} />
)}
</Box>
)}
{showResultForm && quiz?.config.resultInfo.when === "before" && (

@ -16,6 +16,7 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
const quiz = useCurrentQuiz();
const mode = modes;
const { isMobileDevice } = useUADevice();
const isMobile = useMediaQuery(theme.breakpoints.down(650));
if (!quiz) return null;
@ -87,7 +88,6 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
? "linear-gradient(180deg,transparent,#272626)"
: "linear-gradient(270deg,#272626,transparent)"
: "",
backgroundColor: theme.palette.background.default,
color: quiz.config.startpageType === "expanded" ? "white" : "black",
}}
@ -152,7 +152,7 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
overflowWrap: "break-word",
width: "100%",
textAlign: quiz.config.startpageType === "centered" ? "center" : "-moz-initial",
color: theme.palette.text.primary
color: quiz.config.startpageType === "expanded" ? "white" : theme.palette.text.primary
}}
>
{quiz.name}
@ -184,7 +184,14 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
</Box>
<Box
sx={{ mt: "46px", display: "flex", alignItems: "center", justifyContent: "space-between", width: "100%" }}
sx={{
mt: "46px",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
width: "100%",
flexDirection: isMobile ? "column" : "row"
}}
>
<Box sx={{ maxWidth: "300px" }}>
{quiz.config.info.clickable ? (
@ -218,8 +225,8 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
gap: "15px"
}}
>
<NameplateLogo style={{ fontSize: "34px", color: mode[quiz.config.theme] ? "#151515" : "#FFFFFF" }} />
<Typography sx={{ fontSize: "20px", color: mode[quiz.config.theme] ? "#4D4D4D" : "#F5F7FF", whiteSpace: "nowrap", }}>
<NameplateLogo style={{ fontSize: "34px", color: quiz.config.startpageType === "expanded" ? "#FFFFFF" : (mode[quiz.config.theme] ? "#151515" : "#FFFFFF") }} />
<Typography sx={{ fontSize: "20px", color: quiz.config.startpageType === "expanded" ? "#F5F7FF" : (mode[quiz.config.theme] ? "#4D4D4D" : "#F5F7FF"), whiteSpace: "nowrap", }}>
Сделано на PenaQuiz
</Typography>
</Box>
@ -248,116 +255,191 @@ function QuizPreviewLayoutByType({
alignType: QuizStartpageAlignType;
}) {
const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(630));
const isMobile = useMediaQuery(theme.breakpoints.down(650));
function StartPageMobile() {
return(
<Box
sx={{
display: "flex",
flexDirection: "column-reverse",
flexGrow: 1,
justifyContent: "flex-end",
height: "100vh",
"&::-webkit-scrollbar": { width: 0 },
}}
>
<Box
sx={{
width: "100%",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
alignItems: "flex-start",
p: "25px",
height: "80%"
}}
>
{quizHeaderBlock}
<Box
sx={{
height: "80%",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
width: "100%"
}}
>
{quizMainBlock}
</Box>
</Box>
<Box
sx={{
width: "100%",
overflow: "hidden",
}}
>
{backgroundBlock}
</Box>
</Box>
)
}
switch (startpageType) {
case null:
case "standard": {
return (
<Box
sx={{
display: "flex",
flexDirection: alignType === "left" ? "row" : "row-reverse",
flexGrow: 1,
height: "100vh",
"&::-webkit-scrollbar": { width: 0 },
}}
>
<Box
sx={{
width: !isTablet ? "40%" : "100%",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
alignItems: !isTablet ? "flex-start" : "center",
p: "25px",
}}
>
{quizHeaderBlock}
{quizMainBlock}
</Box>
<>
{isMobile ? (
<StartPageMobile/>
) : (
<Box
sx={{
display: "flex",
flexDirection: alignType === "left" ? (isMobile ? "column-reverse" : "row") : "row-reverse",
flexGrow: 1,
justifyContent: isMobile ? "flex-end" : undefined,
height: "100vh",
"&::-webkit-scrollbar": { width: 0 },
}}
>
<Box
sx={{
width: isMobile ? "100%" : "40%",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
alignItems: "flex-start",
p: "25px",
height: isMobile ? "80%" : undefined
}}
>
{quizHeaderBlock}
{quizMainBlock}
</Box>
<Box
sx={{
width: isMobile ? "100%" : "60%",
overflow: "hidden",
}}
>
{backgroundBlock}
</Box>
</Box>
)}
</>
<Box
sx={{
width: "60%",
overflow: "hidden",
}}
>
{backgroundBlock}
</Box>
</Box>
);
}
case "expanded": {
return (
<Box
sx={{
position: "relative",
display: "flex",
justifyContent: startpageAlignTypeToJustifyContent[alignType],
flexGrow: 1,
height: "100%",
"&::-webkit-scrollbar": { width: 0 },
}}
>
<Box
sx={{
width: "40%",
position: "relative",
padding: "16px",
zIndex: 3,
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
alignItems: alignType === "center" ? "center" : "start",
}}
>
{quizHeaderBlock}
{quizMainBlock}
</Box>
<Box
sx={{
position: "absolute",
zIndex: -1,
left: 0,
top: 0,
height: "100%",
width: "100%",
overflow: "hidden",
}}
>
{backgroundBlock}
</Box>
</Box>
<>
{isMobile ? (
<StartPageMobile/>
) : (
<Box
sx={{
position: "relative",
display: "flex",
justifyContent: startpageAlignTypeToJustifyContent[alignType],
flexGrow: 1,
height: "100%",
"&::-webkit-scrollbar": { width: 0 },
}}
>
<Box
sx={{
width: "40%",
position: "relative",
padding: "16px",
zIndex: 3,
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
alignItems: alignType === "center" ? "center" : "start",
}}
>
{quizHeaderBlock}
{quizMainBlock}
</Box>
<Box
sx={{
position: "absolute",
zIndex: -1,
left: 0,
top: 0,
height: "100%",
width: "100%",
overflow: "hidden",
}}
>
{backgroundBlock}
</Box>
</Box>
)
}
</>
);
}
case "centered": {
return (
<Box
sx={{
padding: "16px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
height: "100%",
"&::-webkit-scrollbar": { width: 0 },
overflow: "hidden",
}}
>
{quizHeaderBlock}
{backgroundBlock && (
<Box
sx={{
width: "60%",
overflow: "hidden",
}}
>
{backgroundBlock}
</Box>
)}
{quizMainBlock}
</Box>
<>
{isMobile ? (
<StartPageMobile/>
) : (
<Box
sx={{
padding: "16px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
height: "100%",
"&::-webkit-scrollbar": { width: 0 },
overflow: "hidden",
}}
>
{quizHeaderBlock}
{backgroundBlock && (
<Box
sx={{
width: "60%",
overflow: "hidden",
}}
>
{backgroundBlock}
</Box>
)}
{quizMainBlock}
</Box>
)
}
</>
);
}
default:

@ -58,7 +58,7 @@ export const ViewPage = () => {
if (questions.length === 0 || (questions.length === 1 && questions[0].type === "result")) return <ApologyPage message="Нет созданных вопросов"/>
return (
<ThemeProvider theme={themesPublication?.[quiz?.config.theme]}>
<Box sx={{backgroundColor: theme.palette.background.default}}>
<Box sx={{backgroundColor: quiz.config.startpageType === "expanded" ? undefined : theme.palette.background.default}}>
{!visualStartPage ? (
<StartPageViewPublication setVisualStartPage={setVisualStartPage} />
) : (

@ -5,7 +5,7 @@ import {
FormControlLabel,
Radio,
useTheme,
FormControl,
FormControl, useMediaQuery,
} from "@mui/material";
import { useQuizViewStore, updateAnswer, deleteAnswer } from "@root/quizView";
@ -22,6 +22,7 @@ type EmojiProps = {
export const Emoji = ({ currentQuestion }: EmojiProps) => {
const { answers } = useQuizViewStore();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(650));
const { answer } =
answers.find(
({ questionId }) => questionId === currentQuestion.content.id
@ -49,7 +50,7 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
marginTop: "20px",
}}
>
<Box sx={{ display: "flex", width: "100%", gap: "42px" }}>
<Box sx={{ display: "flex", width: "100%", gap: "42px", flexWrap: "wrap" }}>
{currentQuestion.content.variants.map((variant, index) => (
<FormControl
key={variant.id}

@ -1,5 +1,5 @@
import { useState, useEffect } from "react";
import { Box, Typography, Slider, useTheme } from "@mui/material";
import {Box, Typography, Slider, useTheme, useMediaQuery} from "@mui/material";
import { useDebouncedCallback } from "use-debounce";
import CustomTextField from "@ui_kit/CustomTextField";
@ -19,6 +19,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
const [minRange, setMinRange] = useState<string>("0");
const [maxRange, setMaxRange] = useState<string>("100000000000");
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(650));
const mode = modes;
const quiz = useCurrentQuiz();
const { answers } = useQuizViewStore();
@ -72,6 +73,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
width: "100%",
marginTop: "20px",
gap: "30px",
paddingRight: isMobile ? "10px" : undefined
}}
>
<CustomSlider

@ -2,7 +2,7 @@ import {
Box,
Typography,
Rating as RatingComponent,
useTheme,
useTheme, useMediaQuery,
} from "@mui/material";
import { useQuizViewStore, updateAnswer } from "@root/quizView";
@ -55,6 +55,7 @@ const buttonRatingForm = [
export const Rating = ({ currentQuestion }: RatingProps) => {
const { answers } = useQuizViewStore();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(650));
const { answer } =
answers.find(
({ questionId }) => questionId === currentQuestion.content.id
@ -72,6 +73,7 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
alignItems: "center",
gap: "20px",
marginTop: "20px",
width: isMobile ? "100%" : undefined
}}
>
<Typography sx={{
@ -91,7 +93,11 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
onChange={(_, value) =>
updateAnswer(currentQuestion.content.id, String(value))
}
sx={{ height: "50px", gap: "15px" }}
sx={{ height: "50px",
gap: isMobile ? undefined : "15px",
justifyContent: isMobile ? "space-between" : undefined,
width: isMobile ? "100%" : undefined
}}
max={currentQuestion.content.steps}
icon={form?.icon(theme.palette.primary.main)}
emptyIcon={form?.icon("#9A9AAF")}

@ -1,10 +1,10 @@
import {
Box,
Typography,
RadioGroup,
FormControlLabel,
Radio,
useTheme,
Box,
Typography,
RadioGroup,
FormControlLabel,
Radio,
useTheme, useMediaQuery,
} from "@mui/material";
import gag from "./gag.png"
@ -27,6 +27,7 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
const mode = modes;
const quiz = useCurrentQuiz();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(650));
const { answer } =
answers.find(
({ questionId }) => questionId === currentQuestion.content.id
@ -38,7 +39,13 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
return (
<Box>
<Typography variant="h5" color={theme.palette.text.primary}>{currentQuestion.title}</Typography>
<Box sx={{ display: "flex", marginTop: "20px" }}>
<Box sx={{
display: "flex",
marginTop: "20px",
flexDirection: isMobile ? "column-reverse" : undefined,
gap: isMobile ? "30px" : undefined
}}>
<RadioGroup
name={currentQuestion.id}
value={currentQuestion.content.variants.findIndex(
@ -52,7 +59,7 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
flexBasis: "100%",
}}
>
<Box sx={{ display: "flex", flexDirection: "column", width: "100%" }}>
<Box sx={{ display: "flex", flexDirection: "column", width: "100%", gap: isMobile ? "20px" : undefined }}>
{currentQuestion.content.variants.map((variant, index) => (
<FormControlLabel
key={variant.id}
@ -65,6 +72,7 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
border: `1px solid`,
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
display: "flex",
margin: isMobile ? 0 : undefined,
}}
value={index}
onClick={(event) => {
@ -113,7 +121,7 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
alt=""
/>
:
(variant?.extendedText || "Выберите вариант ответа слева")
(variant?.extendedText || isMobile ? ("Выберите вариант ответа ниже") : ("Выберите вариант ответа слева"))
}
</Box>