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

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

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

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

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

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

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

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

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