вопросы и квизы запрашиваются 1 раз перед работой, стартовая страница публикации отображается по условию настройки

This commit is contained in:
Nastya 2023-12-14 12:40:53 +03:00
parent d1a714903a
commit 0c704d3723
31 changed files with 308 additions and 230 deletions

@ -5,7 +5,7 @@ import "dayjs/locale/ru";
import SigninDialog from "./pages/auth/Signin";
import SignupDialog from "./pages/auth/Signup";
import { ViewPage } from "./pages/ViewPublicationPage";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import { BrowserRouter, Route, Routes, useLocation, useNavigate, Navigate } from "react-router-dom";
import "./index.css";
import ContactFormPage from "./pages/ContactFormPage/ContactFormPage";
import InstallQuiz from "./pages/InstallQuiz/InstallQuiz";
@ -34,6 +34,8 @@ const routeslink = [
export default function App() {
const userId = useUserStore((state) => state.userId);
const location = useLocation()
const navigate = useNavigate()
useUserFetcher({
url: `https://hub.pena.digital/user/${userId}`,
@ -48,23 +50,31 @@ export default function App() {
}
},
});
if (location.state?.redirectTo)
return <Navigate to={location.state.redirectTo} replace state={{ backgroundLocation: location }} />
return (
<>
<ContactFormModal />
<BrowserRouter>
{location.state?.backgroundLocation && (
<Routes>
{routeslink.map((e, i) => (
<Route key={i} path={e.path} element={<Main page={e.page} header={e.header} sidebar={e.sidebar} />} />
))}
<Route path="edit" element={<EditPage />} />
<Route path="crop" element={<ImageCrop />} />
<Route path="/" element={<Landing />} />
<Route path="/signin" element={<SigninDialog />} />
<Route path="/signup" element={<SignupDialog />} />
<Route path="/view" element={<ViewPage />} />
</Routes>
</BrowserRouter>
)}
<Routes location={location.state?.backgroundLocation || location}>
{routeslink.map((e, i) => (
<Route key={i} path={e.path} element={<Main page={e.page} header={e.header} sidebar={e.sidebar} />} />
))}
<Route path="edit" element={<EditPage />} />
<Route path="crop" element={<ImageCrop />} />
<Route path="/" element={<Landing />} />
<Route path="/signin" element={<Navigate to="/" replace state={{ redirectTo: "/signin" }} />} />
<Route path="/signup" element={<Navigate to="/" replace state={{ redirectTo: "/signup" }} />} />/>
<Route path="/view" element={<ViewPage />} />
</Routes>
</>
);
}

@ -18,6 +18,7 @@ function createQuestion(body: CreateQuestionRequest) {
}
async function getQuestionList(body?: Partial<GetQuestionListRequest>) {
console.log("body" , body)
if (!body?.quiz_id) return null;
const response = await makeRequest<GetQuestionListRequest, GetQuestionListResponse>({

@ -12,6 +12,8 @@ import { createRoot } from "react-dom/client";
import "./index.css";
import lightTheme from "./utils/themes/light";
import { SWRConfig } from "swr";
import {BrowserRouter} from "react-router-dom";
dayjs.locale("ru");
@ -28,13 +30,16 @@ root.render(
<DndProvider backend={HTML5Backend}>
<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale="ru" localeText={localeText}>
<ThemeProvider theme={lightTheme}>
<SnackbarProvider
preventDuplicate={true}
style={{ backgroundColor: lightTheme.palette.brightPurple.main }}
>
<CssBaseline />
<App />
</SnackbarProvider>
<BrowserRouter>
<SnackbarProvider
preventDuplicate={true}
style={{ backgroundColor: lightTheme.palette.brightPurple.main }}
>
<CssBaseline />
<App />
</SnackbarProvider>
</BrowserRouter>
</ThemeProvider>
</LocalizationProvider>
</DndProvider>

@ -7,7 +7,7 @@ import QuizLogo from "./images/icons/QuizLogo";
import { useMediaQuery, useTheme } from "@mui/material";
import { setIsContactFormOpen } from "../../stores/contactForm";
import { useUserStore } from "@root/user";
import { useNavigate, Link, } from "react-router-dom";
import { useNavigate, Link, useLocation } from "react-router-dom";
const buttonMenu = ["Меню 1", "Меню 2", "Меню 3", "Меню 4", "Меню 5", "Меню 1", "Меню 2"];
@ -18,6 +18,7 @@ export default function Component() {
const [select, setSelect] = React.useState(0);
const userId = useUserStore((state) => state.userId);
const navigate = useNavigate();
const location = useLocation()
const onClick = () => (userId ? navigate("/list") : navigate("/signin"));

@ -9,7 +9,7 @@ import Blog from './Blog';
import HowItWorks from './HowItWorks';
import BusinessPluses from './BusinessPluses';
import HowToUse from './HowToUse';
import WhatTheySay from './WhatTheySay';
import StartWithTemplates from './StartWithTemplates';
import WhatTheFeatures from './WhatTheFeatures';
import FullScreenDialog from "./headerMobileLanding";
@ -18,6 +18,7 @@ import Collaboration from "./Collaboration";
export default function Landing() {
const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
return (
<>
<CssBaseline />

@ -7,7 +7,8 @@ import { useCurrentQuiz } from "@root/quizes/hooks";
import { updateRootContentId } from "@root/quizes/actions"
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared"
import { useQuestionsStore } from "@root/questions/store";
import { deleteQuestion, cleardragQuestionContentId, updateQuestion, updateOpenedModalSettingsId, getQuestionByContentId, clearRuleForAll } from "@root/questions/actions";
import { deleteQuestion, updateQuestion, updateOpenedModalSettingsId, getQuestionByContentId, clearRuleForAll } from "@root/questions/actions";
import { cleardragQuestionContentId } from "@root/uiTools/actions";
import { withErrorBoundary } from "react-error-boundary";
import { storeToNodes } from "./helper";
@ -22,6 +23,7 @@ import type {
ElementDefinition,
} from "cytoscape";
import { enqueueSnackbar } from "notistack";
import { useUiTools } from "@root/uiTools/store";
type PopperItem = {
id: () => string;
@ -121,7 +123,7 @@ function CsComponent({
}: Props) {
const quiz = useCurrentQuiz();
const { dragQuestionContentId, desireToOpenABranchingModal } = useQuestionsStore()
const { dragQuestionContentId, desireToOpenABranchingModal } = useUiTools()
const trashQuestions = useQuestionsStore().questions
const questions = trashQuestions.filter((question) => question.type !== "result" && question.type !== null)
const [startCreate, setStartCreate] = useState("");
@ -145,9 +147,8 @@ function CsComponent({
}, [desireToOpenABranchingModal])
useLayoutEffect(() => {
updateOpenedModalSettingsId()
console.log("first render CSComponent")
// updateRootContentId(quiz.id, "")
// clearRuleForAll()
// updateRootContentId(quiz.id, "")
// clearRuleForAll()
}, [])
useEffect(() => {
if (modalQuestionTargetContentId.length !== 0 && modalQuestionParentContentId.length !== 0) {
@ -312,7 +313,6 @@ function CsComponent({
const clearDataAfterRemoveNode = ({ targetQuestionContentId, parentQuestionContentId }: { targetQuestionContentId: string, parentQuestionContentId: string }) => {
console.log("target ", targetQuestionContentId, "parent ", parentQuestionContentId)
updateQuestion(targetQuestionContentId, question => {
@ -325,7 +325,6 @@ function CsComponent({
//чистим rule родителя
const parentQuestion = getQuestionByContentId(parentQuestionContentId)
console.log(parentQuestion.content.rule.parentId)
const newRule = {}
const newChildren = [...parentQuestion.content.rule.children]
newChildren.splice(parentQuestion.content.rule.children.indexOf(targetQuestionContentId), 1);
@ -639,7 +638,6 @@ function CsComponent({
},
});
let gearsPopper = null
console.log('POPE', node.data())
if (node.data().root !== true) {
gearsPopper = node.popper({
popper: {
@ -647,7 +645,6 @@ console.log('POPE', node.data())
modifiers: [{ name: "flip", options: { boundary: node } }],
},
content: ([item]) => {
console.log('PEPO', item.id())
const itemId = item.id();
const itemElement = gearsContainer.current?.querySelector(
@ -678,7 +675,6 @@ console.log('POPE', node.data())
};
const onZoom = (event: AbstractEventObject) => {
console.log('ZOOOOM')
const zoom = event.cy.zoom();
//update();

@ -5,6 +5,7 @@ import { updateRootContentId } from "@root/quizes/actions"
import { useCurrentQuiz } from "@root/quizes/hooks"
import { useQuestionsStore } from "@root/questions/store"
import { enqueueSnackbar } from "notistack";
import { useUiTools } from "@root/uiTools/store";
interface Props {
setOpenedModalQuestions: (open: boolean) => void;
@ -17,12 +18,13 @@ export const FirstNodeField = ({ setOpenedModalQuestions, modalQuestionTargetCon
useLayoutEffect(() => {
updateOpenedModalSettingsId()
console.log("first render firstComponent")
updateRootContentId(quiz.id, "")
clearRuleForAll()
// updateRootContentId(quiz.id, "")
// clearRuleForAll()
}, [])
const { dragQuestionContentId, questions } = useQuestionsStore()
const { questions } = useQuestionsStore()
const { dragQuestionContentId } = useUiTools()
const Container = useRef<HTMLDivElement | null>(null);
const modalOpen = () => setOpenedModalQuestions(true)

@ -1,15 +1,15 @@
import { Box } from "@mui/material";
import { FirstNodeField } from "./FirstNodeField";
import CsComponent from "./CsComponent";
import { useQuestionsStore } from "@root/questions/store"
import { useCurrentQuiz } from "@root/quizes/hooks";
import { useState } from "react";
import {BranchingQuestionsModal} from "../BranchingQuestionsModal"
import { useUiTools } from "@root/uiTools/store";
export const BranchingMap = () => {
const quiz = useCurrentQuiz();
const { dragQuestionContentId } = useQuestionsStore()
const { dragQuestionContentId } = useUiTools()
const [modalQuestionParentContentId, setModalQuestionParentContentId] = useState<string>("")
const [modalQuestionTargetContentId, setModalQuestionTargetContentId] = useState<string>("")
const [openedModalQuestions, setOpenedModalQuestions] = useState<boolean>(false)

@ -1,15 +1,16 @@
import {Box, Typography, Switch, useTheme, Button, useMediaQuery, SxProps, Theme} from "@mui/material";
import { QuestionsList } from "./QuestionsList";
import { updateOpenBranchingPanel } from "@root/questions/actions";
import { updateOpenBranchingPanel } from "@root/uiTools/actions";
import {useQuestionsStore} from "@root/questions/store";
import {useRef} from "react";
import { useUiTools } from "@root/uiTools/store";
export const BranchingPanel = (sx?: SxProps<Theme>) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(660));
const {openBranchingPanel} = useQuestionsStore.getState()
const {openBranchingPanel} = useUiTools()
const ref = useRef()
return (
<Box sx={{ userSelect: "none", maxWidth: "350px", width: "100%" }}>
@ -26,10 +27,10 @@ export const BranchingPanel = (sx?: SxProps<Theme>) => {
}}
>
<Switch
clicked={openBranchingPanel}
onChange={(_, value) => {
updateOpenBranchingPanel(value)
}}
checked={openBranchingPanel}
onChange={
(e) => updateOpenBranchingPanel(e.target.checked)
}
sx={{
width: 50,
height: 30,
@ -76,7 +77,7 @@ export const BranchingPanel = (sx?: SxProps<Theme>) => {
/>
<Box>
<Typography ref={ref} sx={{ fontWeight: "bold", color: "#4D4D4D" }}>
Логика ветвления
Логика ветвления
</Typography>
<Typography sx={{ color: "#4D4D4D", fontSize: "12px" }}>
Настройте связи между вопросами

@ -11,7 +11,8 @@ import {
useMediaQuery,
useTheme,
} from "@mui/material";
import { copyQuestion, deleteQuestion, updateOpenBranchingPanel, updateDesireToOpenABranchingModal, deleteQuestionWithTimeout, clearRuleForAll, updateQuestion, getQuestionByContentId } from "@root/questions/actions";
import { copyQuestion, deleteQuestion, deleteQuestionWithTimeout, clearRuleForAll, updateQuestion, getQuestionByContentId } from "@root/questions/actions";
import { updateOpenBranchingPanel, updateDesireToOpenABranchingModal, } from "@root/uiTools/actions";
import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
import { CopyIcon } from "../../assets/icons/questionsPage/CopyIcon";
import Branching from "../../assets/icons/questionsPage/branching";
@ -24,6 +25,7 @@ import { enqueueSnackbar } from "notistack";
import { useQuestionsStore } from "@root/questions/store";
import { updateOpenedModalSettingsId } from "@root/questions/actions";
import { updateRootContentId } from "@root/quizes/actions";
import { useUiTools } from "@root/uiTools/store";
interface Props {
switchState: string;
@ -41,7 +43,8 @@ export default function ButtonsOptions({
const isMobile = useMediaQuery(theme.breakpoints.down(790));
const isWrappMiniButtonSetting = useMediaQuery(theme.breakpoints.down(920));
const quiz = useCurrentQuiz();
const { openBranchingPanel, questions } = useQuestionsStore.getState();
const { questions } = useQuestionsStore.getState();
const { openBranchingPanel } = useUiTools();
const openedModal = () => {
updateOpenedModalSettingsId(question.id);

@ -23,7 +23,7 @@ import ImgIcon from "../../assets/icons/questionsPage/imgIcon";
import SettingIcon from "../../assets/icons/questionsPage/settingIcon";
import { QuizQuestionVariant } from "@model/questionTypes/variant";
import { updateOpenedModalSettingsId } from "@root/questions/actions";
import { updateOpenBranchingPanel, updateDesireToOpenABranchingModal } from "@root/questions/actions";
import { updateOpenBranchingPanel, updateDesireToOpenABranchingModal } from "@root/uiTools/actions";
import { useQuestionsStore } from "@root/questions/store";
import { enqueueSnackbar } from "notistack";
import { useCurrentQuiz } from "@root/quizes/hooks";

@ -3,8 +3,10 @@ import { Box, ListItem, Typography, useTheme } from "@mui/material";
import { memo, useEffect } from "react";
import { Draggable } from "react-beautiful-dnd";
import QuestionsPageCard from "./QuestionPageCard";
import { cancelQuestionDeletion, updateEditSomeQuestion } from "@root/questions/actions";
import { cancelQuestionDeletion } from "@root/questions/actions";
import { updateEditSomeQuestion } from "@root/uiTools/actions";
import { useQuestionsStore } from "@root/questions/store";
import { useUiTools } from "@root/uiTools/store";
type Props = {
@ -15,7 +17,7 @@ type Props = {
function DraggableListItem({ question, isDragging, index }: Props) {
const theme = useTheme();
const { editSomeQuestion } = useQuestionsStore();
const { editSomeQuestion } = useUiTools();
useEffect(() => {
if (editSomeQuestion !== null) {

@ -6,13 +6,16 @@ import { DraggableList } from "./DraggableList";
import { SwitchBranchingPanel } from "./SwitchBranchingPanel";
import { BranchingMap } from "./BranchingMap";
import {useQuestionsStore} from "@root/questions/store";
import { useUiTools } from "@root/uiTools/store";
export const QuestionSwitchWindowTool = () => {
const {openBranchingPanel, questions} = useQuestionsStore.getState()
const {questions} = useQuestionsStore.getState()
const {openBranchingPanel} = useUiTools()
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
console.log("questions ", questions)
console.log("rules ", questions.filter((q) => q.type !== null).map((q) => ({id: q.content.id, rule: q.content.rule})))
return (
<Box sx={{ display: "flex", gap: "20px", flexWrap: "wrap", marginBottom: isMobile ? "20px" : undefined }}>
<Box sx={{ flexBasis: "796px" }}>

@ -17,12 +17,13 @@ import ArrowLeft from "../../assets/icons/questionsPage/arrowLeft";
import BranchingQuestions from "./BranchingModal/BranchingQuestionsModal"
import { QuestionSwitchWindowTool } from "./QuestionSwitchWindowTool";
import { useQuestionsStore } from "@root/questions/store";
import { updateOpenBranchingPanel, updateEditSomeQuestion } from "@root/questions/actions";
import { updateOpenBranchingPanel, updateEditSomeQuestion } from "@root/uiTools/actions";
import { useUiTools } from "@root/uiTools/store";
export default function QuestionsPage() {
const theme = useTheme();
const { openedModalSettingsId, openBranchingPanel } = useQuestionsStore();
const { openedModalSettingsId, openBranchingPanel } = useUiTools();
const isMobile = false//useMediaQuery(theme.breakpoints.down(660));
const quiz = useCurrentQuiz();
useLayoutEffect(() => {

@ -2,11 +2,11 @@ import { useParams } from "react-router-dom";
import { Box, Button, IconButton, Typography } from "@mui/material";
import { ReactComponent as CheckedIcon } from "@icons/checked.svg";
import { useQuestionsStore } from "@root/questions/store";
import { updateDragQuestionContentId } from "@root/questions/actions";
import { useEffect } from "react";
import { AnyTypedQuizQuestion, UntypedQuizQuestion } from "@model/questionTypes/shared";
import { Pencil } from "../../startPage/Sidebar/icons/Pencil";
import {updateOpenBranchingPanel, updateEditSomeQuestion} from "@root/questions/actions"
import { updateOpenBranchingPanel, updateEditSomeQuestion, updateDragQuestionContentId } from "@root/uiTools/actions"
import { useUiTools } from "@root/uiTools/store";
const getItemStyle = (isDragging: any, draggableStyle: any) => ({
@ -24,7 +24,7 @@ const getItemStyle = (isDragging: any, draggableStyle: any) => ({
type AnyQuestion = UntypedQuizQuestion | AnyTypedQuizQuestion
export const QuestionsList = () => {
const { desireToOpenABranchingModal } = useQuestionsStore()
const { desireToOpenABranchingModal } = useUiTools()
const trashQuestions = useQuestionsStore().questions
const questions = trashQuestions.filter((question) => question.type !== "result")

@ -3,18 +3,21 @@
import {Box, Typography, Switch, useTheme, Button, useMediaQuery} from "@mui/material";
import { QuestionsList } from "./QuestionsList";
import { updateOpenBranchingPanel } from "@root/questions/actions";
import { updateOpenBranchingPanel } from "@root/uiTools/actions";
import {useQuestionsStore} from "@root/questions/store";
import {useRef} from "react";
import { useUiTools } from "@root/uiTools/store";
export const SwitchBranchingPanel = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(660));
const {openBranchingPanel} = useQuestionsStore.getState()
console.log(openBranchingPanel)
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const {openBranchingPanel} = useUiTools()
const ref = useRef()
return (
return ( !isTablet || openBranchingPanel ?
<Box sx={{ userSelect: "none", maxWidth: "350px", width: "100%" }}>
<Box
sx={{
@ -29,8 +32,8 @@ export const SwitchBranchingPanel = () => {
>
<Switch
checked={openBranchingPanel}
onChange={
(e) => updateOpenBranchingPanel(e.target.checked)
onChange={
(e) => updateOpenBranchingPanel(e.target.checked)
}
sx={{
width: 50,
@ -88,5 +91,7 @@ export const SwitchBranchingPanel = () => {
</Box>
{ openBranchingPanel && <QuestionsList /> }
</Box>
:
<></>
);
};

@ -16,17 +16,14 @@ export const FirstEntry = () => {
const create = () => {
if (quiz?.config.haveRoot) {
console.log("createFrontResult")
questions
.filter((question:AnyTypedQuizQuestion) => {
console.log(question)
return question.type !== null && question.content.rule.parentId.length !== 0 && question.content.rule.children.length === 0
})
.forEach(question => {
createFrontResult(quiz.id, question.content.id)
})
} else {
console.log("createFrontResult")
createFrontResult(quiz.id, "line")
}
}

@ -21,7 +21,6 @@ export const ResultSettings = () => {
const { questions } = useQuestionsStore()
const quiz = useCurrentQuiz()
const results = useQuestionsStore().questions.filter((q): q is QuizQuestionResult => q.type === "result")
console.log("опросник ", quiz)
const [quizExpand, setQuizExpand] = useState(true)
const [resultContract, setResultContract] = useState(true)
const isReadyToLeaveRef = useRef(true);

@ -19,11 +19,9 @@ interface Props {
}
export const StartPageViewPublication = ({setVisualStartPage}:Props) => {
console.log("startpage")
const theme = useTheme();
const quiz = useCurrentQuiz();
const { isMobileDevice } = useUADevice();
console.log(quiz)
if (!quiz) return null;

@ -10,28 +10,38 @@ import { quizApi } from "@api/quiz";
import { setQuizes } from "@root/quizes/actions";
import { isAxiosError } from "axios";
import { devlog } from "@frontend/kitui";
import { useQuizStore } from "@root/quizes/store";
import type { AnyTypedQuizQuestion } from "../../model/questionTypes/shared";
import { enqueueSnackbar } from "notistack";
import { useQuestionsStore } from "@root/questions/store";
import { setQuestions } from "@root/questions/actions";
import { questionApi } from "@api/question";
export const ViewPage = () => {
useSWR("quizes", () => quizApi.getList(), {
onSuccess: setQuizes,
onError: error => {
const message = isAxiosError<string>(error) ? (error.response?.data ?? "") : "";
devlog("Error getting quiz list", error);
enqueueSnackbar(`Не удалось получить квизы. ${message}`);
},
});
const quiz = useCurrentQuiz();
console.log(quiz)
const { questions } = useQuestions();
const [visualStartPage, setVisualStartPage] = useState<boolean>(
!quiz?.config.noStartPage
);
const { editQuizId } = useQuizStore();
const { questions } = useQuestionsStore();
useEffect(() => {
const getData = async () => {
const quizes = await quizApi.getList()
setQuizes(quizes)
const questions = await questionApi.getList({ quiz_id: editQuizId })
setQuestions(questions)
}
getData()
}, [])
useEffect(() => {
setVisualStartPage(quiz?.config.noStartPage)
}, [questions])
const [visualStartPage, setVisualStartPage] = useState<boolean>();
console.log("quiz ", quiz)
console.log("quiz.config ", quiz?.config)
console.log("quiz.config.noStartPage ", quiz?.config.noStartPage)
useEffect(() => {
const link = document.querySelector('link[rel="icon"]');
@ -45,9 +55,11 @@ export const ViewPage = () => {
questions.filter(({ type }) => type) as AnyTypedQuizQuestion[]
).sort((previousItem, item) => previousItem.page - item.page);
console.log("visualStartPage ", visualStartPage)
if (visualStartPage === undefined) return <></>
return (
<Box>
{visualStartPage ? (
{!visualStartPage ? (
<StartPageViewPublication setVisualStartPage={setVisualStartPage}/>
) : (
<Question questions={filteredQuestions} />

@ -47,7 +47,6 @@ export const Number = ({ currentQuestion }: NumberProps) => {
const max = window.Number(currentQuestion.content.range.split("—")[1]);
useEffect(() => {
console.log("ans", currentQuestion.content.start);
if (answer) {
setMinRange(answer.split("—")[0]);
setMaxRange(answer.split("—")[1]);

@ -24,7 +24,7 @@ type RatingProps = {
const buttonRatingForm = [
{
name: "star",
icon: (color: string) => <StarIconMini width={35} color={color} />,
icon: (color: string) => <StarIconMini width={50} color={color} />,
},
{
name: "trophie",

@ -1,14 +1,14 @@
import { login } from "@api/auth";
import CloseIcon from "@mui/icons-material/Close";
import {
Box,
Button,
Dialog,
IconButton,
Link,
Typography,
useMediaQuery,
useTheme,
Box,
Button,
Dialog,
IconButton,
Link,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import { setUserId, useUserStore } from "@root/user";
import InputTextfield from "@ui_kit/InputTextfield";
@ -17,7 +17,7 @@ import PasswordInput from "@ui_kit/passwordInput";
import { useFormik } from "formik";
import { enqueueSnackbar } from "notistack";
import { useEffect, useState } from "react";
import { Link as RouterLink, useNavigate } from "react-router-dom";
import { Link as RouterLink, useNavigate, useLocation } from "react-router-dom";
import { object, string } from "yup";
interface Values {
@ -43,6 +43,8 @@ export default function SigninDialog() {
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
const navigate = useNavigate();
const location = useLocation();
const formik = useFormik<Values>({
initialValues,
validationSchema,
@ -110,11 +112,11 @@ export default function SigninDialog() {
borderRadius: "12px",
boxShadow: "0px 15px 80px rgb(210 208 225 / 70%)",
"& .MuiFormHelperText-root.Mui-error, & .MuiFormHelperText-root.Mui-error.MuiFormHelperText-filled":
{
position: "absolute",
top: "46px",
margin: "0",
},
{
position: "absolute",
top: "46px",
margin: "0",
},
}}
>
<IconButton
@ -153,7 +155,7 @@ export default function SigninDialog() {
id="email"
label="Email"
gap={upMd ? "10px" : "10px"}
/>
/>
<PasswordInput
TextfieldProps={{
value: formik.values.password,
@ -190,16 +192,17 @@ export default function SigninDialog() {
Войти
</Button>
{/* <Link
component={RouterLink}
to="/"
href="#"
sx={{
color: "#4D4D4D",
mb: "15px",
}}
>
Забыли пароль?
</Link> */}
component={RouterLink}
to="/"
href="#"
sx={{
color: "#4D4D4D",
mb: "15px",
}}
>
Забыли пароль?
</Link> */}
<Box
sx={{
display: "flex",

@ -17,7 +17,7 @@ import PasswordInput from "@ui_kit/passwordInput";
import { useFormik } from "formik";
import { enqueueSnackbar } from "notistack";
import { useEffect, useState } from "react";
import { Link as RouterLink, useNavigate } from "react-router-dom";
import {Link as RouterLink, useLocation, useNavigate} from "react-router-dom";
import { object, ref, string } from "yup";
interface Values {
@ -50,6 +50,8 @@ export default function SignupDialog() {
const user = useUserStore((state) => state.user);
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
const location = useLocation()
const navigate = useNavigate();
const formik = useFormik<Values>({
initialValues,
@ -220,6 +222,7 @@ export default function SignupDialog() {
<Link
component={RouterLink}
to="/signin"
state={{ backgroundLocation: location.state.backgroundLocation }}
sx={{
color: "#7E2AEA",
mt: "auto",

@ -29,36 +29,36 @@ import { useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import useSWR from "swr";
import { SidebarMobile } from "./Sidebar/SidebarMobile";
import {cleanQuestions, updateOpenBranchingPanel} from "@root/questions/actions";
import {BranchingPanel} from "../Questions/BranchingPanel";
import {setQuestions} from "@root/questions/actions";
import {useQuestionsStore} from "@root/questions/store";
import { useQuestions } from "@root/questions/hooks";
import { cleanQuestions } from "@root/questions/actions";
import { updateOpenBranchingPanel } from "@root/uiTools/actions";
import { BranchingPanel } from "../Questions/BranchingPanel";
import { setQuestions } from "@root/questions/actions";
import { useQuestionsStore } from "@root/questions/store";
import { useQuizes } from "@root/quizes/hooks";
import { questionApi } from "@api/question";
import { useUiTools } from "@root/uiTools/store";
export default function EditPage() {
const quiz = useCurrentQuiz();
const { editQuizId } = useQuizStore();
console.log("get questions")
useSWR(["questions", quiz?.backendId], ([, id]) => questionApi.getList({ quiz_id: id }), {
onSuccess: setQuestions,
onError: error => {
const message = isAxiosError<string>(error) ? (error.response?.data ?? "") : "";
useEffect(() => {
const getData = async () => {
const quizes = await quizApi.getList()
setQuizes(quizes)
devlog("Error getting question list", error);
enqueueSnackbar(`Не удалось получить вопросы. ${message}`);
const questions = await questionApi.getList({ quiz_id: editQuizId })
setQuestions(questions)
}
});
getData()
}, [])
const {openBranchingPanel, questions} = useQuestionsStore.getState()
const { openBranchingPanel } = useUiTools()
const theme = useTheme();
const navigate = useNavigate();
const editQuizId = useQuizStore(state => state.editQuizId);
const currentStep = useQuizStore(state => state.currentStep);
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const isMobile = useMediaQuery(theme.breakpoints.down(660));
@ -74,6 +74,7 @@ export default function EditPage() {
cleanQuestions();
}, []);
return (
<>
{/*хедер*/}
@ -237,7 +238,7 @@ export default function EditPage() {
</>
}
</Box>
{isTablet && [1, 2, 3].includes(currentStep) && (
{isTablet &&
<Box
sx={{
position: "absolute",
@ -251,72 +252,74 @@ export default function EditPage() {
background: "#FFF",
}}
>
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "15px",
padding: "18px",
background: "#fff",
borderRadius: "12px",
boxShadow: "0px 10px 30px #e7e7e7",
}}
>
<Switch
checked={openBranchingPanel}
onChange={
(e) => updateOpenBranchingPanel(e.target.checked)
}
{[1, 2].includes(currentStep) && !openBranchingPanel && (
<Box
sx={{
width: 50,
height: 30,
padding: 0,
"& .MuiSwitch-switchBase": {
padding: 0,
margin: "2px",
transitionDuration: "300ms",
"&.Mui-checked": {
transform: "translateX(20px)",
color: theme.palette.brightPurple.main,
"& + .MuiSwitch-track": {
backgroundColor: "#E8DCF9",
opacity: 1,
border: 0,
},
"&.Mui-disabled + .MuiSwitch-track": { opacity: 0.5 },
},
"&.Mui-disabled .MuiSwitch-thumb": {
color:
theme.palette.mode === "light"
? theme.palette.grey[100]
: theme.palette.grey[600],
},
"&.Mui-disabled + .MuiSwitch-track": {
opacity: theme.palette.mode === "light" ? 0.7 : 0.3,
},
},
"& .MuiSwitch-thumb": {
boxSizing: "border-box",
width: 25,
height: 25,
},
"& .MuiSwitch-track": {
borderRadius: 13,
backgroundColor:
theme.palette.mode === "light" ? "#E9E9EA" : "#39393D",
opacity: 1,
transition: theme.transitions.create(["background-color"], {
duration: 500,
}),
},
display: "flex",
alignItems: "center",
gap: "15px",
padding: "18px",
background: "#fff",
borderRadius: "12px",
boxShadow: "0px 10px 30px #e7e7e7",
}}
/>
<Box>
<Typography sx={{ fontWeight: "bold", color: "#4D4D4D" }}>
Логика ветвления
</Typography>
>
<Switch
checked={openBranchingPanel}
onChange={
(e) => updateOpenBranchingPanel(e.target.checked)
}
sx={{
width: 50,
height: 30,
padding: 0,
"& .MuiSwitch-switchBase": {
padding: 0,
margin: "2px",
transitionDuration: "300ms",
"&.Mui-checked": {
transform: "translateX(20px)",
color: theme.palette.brightPurple.main,
"& + .MuiSwitch-track": {
backgroundColor: "#E8DCF9",
opacity: 1,
border: 0,
},
"&.Mui-disabled + .MuiSwitch-track": { opacity: 0.5 },
},
"&.Mui-disabled .MuiSwitch-thumb": {
color:
theme.palette.mode === "light"
? theme.palette.grey[100]
: theme.palette.grey[600],
},
"&.Mui-disabled + .MuiSwitch-track": {
opacity: theme.palette.mode === "light" ? 0.7 : 0.3,
},
},
"& .MuiSwitch-thumb": {
boxSizing: "border-box",
width: 25,
height: 25,
},
"& .MuiSwitch-track": {
borderRadius: 13,
backgroundColor:
theme.palette.mode === "light" ? "#E9E9EA" : "#39393D",
opacity: 1,
transition: theme.transitions.create(["background-color"], {
duration: 500,
}),
},
}}
/>
<Box>
<Typography sx={{ fontWeight: "bold", color: "#4D4D4D" }}>
Логика ветвления
</Typography>
</Box>
</Box>
</Box>
)}
<Button
variant="contained"
sx={{
@ -328,7 +331,8 @@ export default function EditPage() {
Опубликовать
</Button>
</Box>
)}
}
</Box>
</>
);

@ -99,7 +99,6 @@ const updateQuestionOrders = () => {
const questions = useQuestionsStore.getState().questions.filter(
(question): question is AnyTypedQuizQuestion => question.type !== null && question.type !== "result"
);
console.log(questions);
questions.forEach((question, index) => {
updateQuestion(question.id, question => {
@ -386,13 +385,16 @@ export const createTypedQuestion = async (
});
export const deleteQuestion = async (questionId: string) => requestQueue.enqueue(async () => {
console.log("Я получил запрос на удаление. ИД - ", questionId)
const question = useQuestionsStore.getState().questions.find(q => q.id === questionId);
console.log("delete question ", question)
if (!question) return;
if (question.type === null) {
console.log("removeQuestion")
removeQuestion(questionId);
return;
}
@ -461,9 +463,7 @@ function setProducedState<A extends string | { type: unknown; }>(
};
export const cleardragQuestionContentId = () => {
useQuestionsStore.setState({ dragQuestionContentId: null });
};
export const getQuestionById = (questionId: string | null) => {
if (questionId === null) return null;
@ -479,13 +479,10 @@ export const getQuestionByContentId = (questionContentId: string | null) => {
};
export const updateOpenedModalSettingsId = (id?: string) => useQuestionsStore.setState({ openedModalSettingsId: id ? id : null });
export const updateDragQuestionContentId = (contentId?: string) => {
useQuestionsStore.setState({ dragQuestionContentId: contentId ? contentId : null });
};
export const clearRuleForAll = () => {
const { questions } = useQuestionsStore.getState();
console.log(questions)
questions.forEach(question => {
if (question.type !== null && (question.content.rule.main.length > 0 || question.content.rule.default.length > 0 || question.content.rule.parentId.length > 0)) {
updateQuestion(question.content.id, question => {
@ -497,23 +494,6 @@ export const clearRuleForAll = () => {
});
};
export const updateOpenBranchingPanel = (value: boolean) => useQuestionsStore.setState({ openBranchingPanel: value });
let UDTOABM: ReturnType<typeof setTimeout>;
export const updateDesireToOpenABranchingModal = (contentId: string) => {
useQuestionsStore.setState({ desireToOpenABranchingModal: contentId });
clearTimeout(UDTOABM);
UDTOABM = setTimeout(() => {
useQuestionsStore.setState({ desireToOpenABranchingModal: null });
}, 7000);
};
export const clearDesireToOpenABranchingModal = () => {
useQuestionsStore.setState({ desireToOpenABranchingModal: null });
};
export const updateEditSomeQuestion = (contentId?: string) => {
useQuestionsStore.setState({ editSomeQuestion: contentId === undefined ? null : contentId });
};
export const createFrontResult = (quizId: number, parentContentId?: string) => setProducedState(state => {
const frontId = nanoid();

@ -6,6 +6,7 @@ import useSWR from "swr";
import { setQuestions } from "./actions";
import { useQuestionsStore } from "./store";
import { useCurrentQuiz } from "@root/quizes/hooks";
import { useEffect } from "react";
export function useQuestions() {

@ -5,20 +5,10 @@ import { devtools } from "zustand/middleware";
export type QuestionsStore = {
questions: (AnyTypedQuizQuestion | UntypedQuizQuestion)[];
openedModalSettingsId: string | null;
dragQuestionContentId: string | null;
openBranchingPanel: boolean;
desireToOpenABranchingModal: string | null;
editSomeQuestion: string | null;
};
const initialState: QuestionsStore = {
questions: [],
openedModalSettingsId: null as null,
dragQuestionContentId: null,
openBranchingPanel: false,
desireToOpenABranchingModal: null as null,
editSomeQuestion: null as null,
};

@ -7,6 +7,7 @@ import { devlog } from "@frontend/kitui";
import { enqueueSnackbar } from "notistack";
export function useQuizes() {
const { isLoading, error, isValidating } = useSWR("quizes", () => quizApi.getList(), {
onSuccess: setQuizes,
@ -25,10 +26,9 @@ export function useQuizes() {
}
export function useCurrentQuiz() {
const quizId = useQuizStore(state => state.editQuizId);
const { quizes } = useQuizes();
const { quizes, editQuizId } = useQuizStore();
const quiz = quizes.find(q => q.backendId === quizId);
const quiz = quizes.find(q => q.backendId === editQuizId);
return quiz;
}

@ -0,0 +1,31 @@
import { useUiTools } from "./store";
export const updateOpenBranchingPanel = (value: boolean) => useUiTools.setState({ openBranchingPanel: value });
export const cleardragQuestionContentId = () => {
useUiTools.setState({ dragQuestionContentId: null });
};
export const updateDragQuestionContentId = (contentId?: string) => {
useUiTools.setState({ dragQuestionContentId: contentId ? contentId : null });
};
let UDTOABM: ReturnType<typeof setTimeout>;
export const updateDesireToOpenABranchingModal = (contentId: string) => {
useUiTools.setState({ desireToOpenABranchingModal: contentId });
clearTimeout(UDTOABM);
UDTOABM = setTimeout(() => {
useUiTools.setState({ desireToOpenABranchingModal: null });
}, 7000);
};
export const clearDesireToOpenABranchingModal = () => {
useUiTools.setState({ desireToOpenABranchingModal: null });
};
export const updateEditSomeQuestion = (contentId?: string) => {
useUiTools.setState({ editSomeQuestion: contentId === undefined ? null : contentId });
};

@ -0,0 +1,30 @@
import { create } from "zustand";
import { devtools } from "zustand/middleware";
export type UiTools = {
openedModalSettingsId: string | null;
dragQuestionContentId: string | null;
openBranchingPanel: boolean;
desireToOpenABranchingModal: string | null;
editSomeQuestion: string | null;
};
const initialState: UiTools = {
openedModalSettingsId: null as null,
dragQuestionContentId: null,
openBranchingPanel: false,
desireToOpenABranchingModal: null as null,
editSomeQuestion: null as null,
};
export const useUiTools = create<UiTools>()(
devtools(
() => initialState,
{
name: "UiTools",
enabled: process.env.NODE_ENV === "development",
trace: process.env.NODE_ENV === "development",
}
)
);