add question select for preview

This commit is contained in:
nflnkr 2024-04-11 17:11:43 +03:00
parent 75d313e0d7
commit a5051e8ebc
8 changed files with 190 additions and 97 deletions

@ -6,93 +6,53 @@ import { useQuizData } from "@contexts/QuizDataContext";
import Stepper from "@ui_kit/Stepper";
type FooterProps = {
stepNumber: number | null;
nextButton: ReactNode;
prevButton: ReactNode;
stepNumber: number | null;
nextButton: ReactNode;
prevButton: ReactNode;
};
export const Footer = ({ stepNumber, nextButton, prevButton }: FooterProps) => {
const theme = useTheme();
const { questions, settings } = useQuizData();
const questionsAmount = questions.filter(
({ type }) => type !== "result"
).length;
if (stepNumber === null) stepNumber = -1
console.log("stepNumber ", stepNumber)
return (
<Box
sx={{
position: "relative",
padding: "15px 0",
borderTop: `1px solid #9A9AAF80`,
height: "75px",
display: "flex",
background: settings.cfg.design
? "rgba(154,154,175, 0.2)"
: "transparent",
}}
>
<Box
sx={{
width: "100%",
maxWidth: "1410px",
padding: "10px",
margin: "0 auto",
display: "flex",
alignItems: "center",
gap: "10px",
}}
>
{/*{mode[settings.cfg.theme] ? (*/}
{/* <NameplateLogoFQ style={{ fontSize: "34px", width:"200px", height:"auto" }} />*/}
{/*):(*/}
{/* <NameplateLogoFQDark style={{ fontSize: "34px", width:"200px", height:"auto" }} />*/}
{/*)}*/}
{
questions.every(({ content }) => content.rule.parentId !== "root") !== null // null when branching enabled
&&
stepNumber !== null && (
<Box sx={{ flexGrow: 1 }}>
<Typography sx={{ color: theme.palette.text.primary }}>
Вопрос {stepNumber} из {questionsAmount}
</Typography>
<Stepper activeStep={stepNumber} steps={questionsAmount} />
</Box>
)}
const theme = useTheme();
const { questions, settings } = useQuizData();
const questionsAmount = questions.filter(
({ type }) => type !== "result"
).length;
return (
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "10px",
marginRight: "auto",
// color: theme.palette.grey1.main,
}}
>
{/* <Typography>Шаг</Typography>
<Typography
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
fontWeight: "bold",
borderRadius: "50%",
width: "30px",
height: "30px",
color: "#FFF",
background: theme.palette.brightPurple.main,
position: "relative",
padding: "15px 0",
borderTop: `1px solid #9A9AAF80`,
height: "75px",
display: "flex",
background: settings.cfg.design
? "rgba(154,154,175, 0.2)"
: "transparent",
}}
>
{stepNumber} */}
{/* </Typography> */}
{/* <Typography>Из</Typography>
<Typography sx={{ fontWeight: "bold" }}>
{questions.length}
</Typography> */}
>
<Box
sx={{
width: "100%",
maxWidth: "1410px",
padding: "10px",
margin: "0 auto",
display: "flex",
alignItems: "center",
gap: "10px",
}}
>
{stepNumber !== null && (
<Box sx={{ flexGrow: 1 }}>
<Typography sx={{ color: theme.palette.text.primary }}>
Вопрос {stepNumber} из {questionsAmount}
</Typography>
<Stepper activeStep={stepNumber} steps={questionsAmount} />
</Box>
)}
{prevButton}
{nextButton}
</Box>
</Box>
{prevButton}
{nextButton}
</Box>
</Box>
);
);
};

@ -21,14 +21,15 @@ import { NameplateLogoFQDark } from "@icons/NameplateLogoFQDark";
import { notReachable } from "@utils/notReachable";
import { quizThemes } from "@utils/themes/Publication/themePublication";
import type { ReactNode } from "react";
import { DESIGN_LIST } from "@/utils/designList";
import type { ReactNode } from "react";
type Props = {
currentQuestion: RealTypedQuizQuestion;
currentQuestionStepNumber: number | null;
nextButton: ReactNode;
prevButton: ReactNode;
questionSelect: ReactNode;
};
export const Question = ({
@ -36,6 +37,7 @@ export const Question = ({
currentQuestionStepNumber,
nextButton,
prevButton,
questionSelect,
}: Props) => {
const theme = useTheme();
const { settings, show_badge } = useQuizData();
@ -118,6 +120,7 @@ export const Question = ({
)}
</Box>
</Box>
{questionSelect}
<Footer
stepNumber={currentQuestionStepNumber}
prevButton={prevButton}

@ -0,0 +1,112 @@
import { useQuizData } from "@/contexts/QuizDataContext";
import { AnyTypedQuizQuestion } from "@/model/questionTypes/shared";
import { Box, FormControl, MenuItem, Select as MuiSelect, useTheme } from "@mui/material";
interface Props {
selectedQuestion: AnyTypedQuizQuestion;
setQuestion: (questionIdF: string) => void;
}
export default function QuestionSelect({ selectedQuestion, setQuestion }: Props) {
const theme = useTheme();
const { questions, preview } = useQuizData();
if (!preview) return null;
return (
<Box sx={{
p: "20px",
display: "flex",
justifyContent: "center",
}}>
<FormControl
fullWidth
size="small"
sx={{
maxWidth: "500px",
minWidth: "200px",
height: "48px",
}}
className="cancel"
>
<MuiSelect
id="category-select"
variant="outlined"
value={selectedQuestion.id}
placeholder="Заголовок вопроса"
onChange={({ target }) => {
setQuestion(target.value);
}}
sx={{
height: "48px",
borderRadius: "8px",
"& .MuiOutlinedInput-notchedOutline": {
border: `1px solid ${theme.palette.primary.main} !important`,
},
"& .MuiSelect-icon": {
color: theme.palette.primary.main,
},
}}
MenuProps={{
PaperProps: {
sx: {
mt: "8px",
p: "4px",
borderRadius: "8px",
border: "1px solid #EEE4FC",
boxShadow: "0px 8px 24px rgba(210, 208, 225, 0.4)",
backgroundColor: theme.palette.background.default,
},
},
MenuListProps: {
sx: {
py: 0,
display: "flex",
flexDirection: "column",
gap: "8px",
"& .Mui-selected": {
backgroundColor: theme.palette.background.default,
color: theme.palette.primary.main,
},
},
},
}}
inputProps={{
sx: {
color: theme.palette.primary.main,
display: "block",
px: "9px",
gap: "20px",
width: "87%",
overflow: "hidden",
textOverflow: "ellipsis",
},
}}
>
{questions.filter((q) => q.type !== "result").map(
(question, index) => (
<MenuItem
key={question.id}
value={question.id}
sx={{
display: "flex",
alignItems: "center",
gap: "20px",
p: "4px",
borderRadius: "5px",
color: "#9A9AAF",
wordBreak: "break-word",
whiteSpace: "normal",
}}
>
{`${index + 1}. ${question.title}`}
</MenuItem>
),
)}
</MuiSelect>
</FormControl>
</Box>
);
}

@ -5,6 +5,7 @@ import { useQuizViewStore } from "@stores/quizView";
import { useQuestionFlowControl } from "@utils/hooks/useQuestionFlowControl";
import { notReachable } from "@utils/notReachable";
import { quizThemes } from "@utils/themes/Publication/themePublication";
import "https://markknol.github.io/console-log-viewer/console-log-viewer.js";
import { enqueueSnackbar } from "notistack";
import { ReactElement, useEffect } from "react";
import { ContactForm } from "./ContactForm";
@ -13,7 +14,7 @@ import { ResultForm } from "./ResultForm";
import { StartPageViewPublication } from "./StartPageViewPublication";
import NextButton from "./tools/NextButton";
import PrevButton from "./tools/PrevButton";
import "https://markknol.github.io/console-log-viewer/console-log-viewer.js"
import QuestionSelect from "./QuestionSelect";
export default function ViewPublicationPage() {
const { settings, recentlyCompleted, quizId, preview, changeFaviconAndTitle } = useQuizData();
@ -27,6 +28,7 @@ export default function ViewPublicationPage() {
moveToPrevQuestion,
moveToNextQuestion,
showResultAfterContactForm,
setQuestion,
} = useQuestionFlowControl();
const isAnswer = answers.some(ans => ans.questionId === currentQuestion.id);
@ -81,7 +83,14 @@ export default function ViewPublicationPage() {
}
moveToNextQuestion();
}}
/>}
/>
}
questionSelect={
<QuestionSelect
selectedQuestion={currentQuestion}
setQuestion={setQuestion}
/>
}
/>
);
break;

@ -1,22 +1,23 @@
import {Button, useTheme} from "@mui/material";
import {useRootContainerSize} from "../../../contexts/RootContainerWidthContext";
import { Button, useTheme } from "@mui/material";
import { useRootContainerSize } from "../../../contexts/RootContainerWidthContext";
import { quizThemes } from "@utils/themes/Publication/themePublication";
import { useQuizData } from "@contexts/QuizDataContext";
interface Props{
interface Props {
isPreviousButtonEnabled: boolean,
moveToPrevQuestion: () => void,
}
export default function PrevButton ({isPreviousButtonEnabled, moveToPrevQuestion}: Props) {
export default function PrevButton({ isPreviousButtonEnabled, moveToPrevQuestion }: Props) {
const theme = useTheme();
const { settings } = useQuizData();
const isMobileMini = useRootContainerSize() < 382;
return(
return (
<Button
disabled={!isPreviousButtonEnabled}
variant="contained"
sx={{
ml: "auto",
fontSize: "16px",
padding: "10px 15px",
color: quizThemes[settings.cfg.theme].isLight ? theme.palette.primary.main : "#FFFFFF",
@ -34,5 +35,5 @@ export default function PrevButton ({isPreviousButtonEnabled, moveToPrevQuestion
>
{isMobileMini ? "←" : "← Назад"}
</Button>
)
}
);
}

@ -35,10 +35,10 @@ interface QuizViewActions {
export const QuizViewContext = createContext<ReturnType<typeof createQuizViewStore> | null>(null);
export function useQuizViewStore<U>(selector: (state: QuizViewStore & QuizViewActions) => U): U {
const context = useContext(QuizViewContext);
if (!context) throw new Error("QuizViewStore context is null");
const store = useContext(QuizViewContext);
if (!store) throw new Error("QuizViewStore context is null");
return useStore(context, selector);
return useStore(store, selector);
}
export const createQuizViewStore = () => createStore<QuizViewStore & QuizViewActions>()(

@ -149,7 +149,7 @@ export function useQuestionFlowControl() {
settings.cfg.resultInfo.showResultForm === "after"
|| isResultQuestionEmpty(nextQuestion)
) setCurrentQuizStep("contactform");
}, [nextQuestion, settings.cfg.resultInfo.showResultForm]);
}, [nextQuestion, setCurrentQuizStep, settings.cfg.resultInfo.showResultForm]);
const showResultAfterContactForm = useCallback(() => {
if (currentQuestion.type !== "result") throw new Error("Current question is not result");
@ -159,7 +159,7 @@ export function useQuestionFlowControl() {
}
setCurrentQuizStep("question");
}, [currentQuestion]);
}, [currentQuestion, setCurrentQuizStep]);
const moveToPrevQuestion = useCallback(() => {
if (!prevQuestion) throw new Error("Previous question not found");
@ -175,6 +175,13 @@ export function useQuestionFlowControl() {
setCurrentQuestion(nextQuestion);
}, [nextQuestion, showResult]);
const setQuestion = useCallback((questionId: string) => {
const question = questions.find(q => q.id === questionId);
if (!question) return;
setCurrentQuestion(question);
}, [questions]);
const isPreviousButtonEnabled = Boolean(prevQuestion);
const isNextButtonEnabled = useMemo(() => {
@ -202,5 +209,6 @@ export function useQuestionFlowControl() {
moveToPrevQuestion,
moveToNextQuestion,
showResultAfterContactForm,
setQuestion,
};
}

@ -1,6 +1,6 @@
{
"name": "@frontend/squzanswerer",
"version": "1.0.25",
"version": "1.0.26",
"type": "module",
"main": "./dist-package/index.js",
"module": "./dist-package/index.js",