diff --git a/package.json b/package.json index 3208fa17..43f2c04c 100755 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "@craco/craco": "^7.0.0", "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", - "@frontend/kitui": "^1.0.54", + "@frontend/kitui": "^1.0.55", "@mui/icons-material": "^5.10.14", "@mui/material": "^5.10.14", "@mui/x-date-pickers": "^6.16.1", diff --git a/src/App.tsx b/src/App.tsx index 81c5ada5..7136bf2e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -16,8 +16,8 @@ import { ResultSettings } from "./pages/ResultPage/ResultSettings"; import MyQuizzesFull from "./pages/createQuize/MyQuizzesFull"; import Main from "./pages/main"; import EditPage from "./pages/startPage/EditPage"; -import { clearAuthToken, getMessageFromFetchError, useUserFetcher } from "@frontend/kitui"; -import { clearUserData, setUser, useUserStore } from "@root/user"; +import { clearAuthToken, getMessageFromFetchError, useUserAccountFetcher, useUserFetcher } from "@frontend/kitui"; +import { clearUserData, setUser, setUserAccount, useUserStore } from "@root/user"; import { enqueueSnackbar } from "notistack"; import PrivateRoute from "@ui_kit/PrivateRoute"; @@ -26,59 +26,75 @@ import { Restore } from "./pages/startPage/Restore"; dayjs.locale("ru"); const routeslink = [ - { path: "/list", page: , header: false, sidebar: false }, - { path: "/questions/:quizId", page: , header: true, sidebar: true }, - { path: "/contacts", page: , header: true, sidebar: true }, - { path: "/result", page: , header: true, sidebar: true }, - { path: "/settings", page: , header: true, sidebar: true }, + { path: "/list", page: , header: false, sidebar: false }, + { path: "/questions/:quizId", page: , header: true, sidebar: true }, + { path: "/contacts", page: , header: true, sidebar: true }, + { path: "/result", page: , header: true, sidebar: true }, + { path: "/settings", page: , header: true, sidebar: true }, ] as const; export default function App() { - const userId = useUserStore((state) => state.userId); - const location = useLocation(); - const navigate = useNavigate(); + const userId = useUserStore((state) => state.userId); + const location = useLocation(); + const navigate = useNavigate(); - useUserFetcher({ - url: `https://hub.pena.digital/user/${userId}`, - userId, - onNewUser: setUser, - onError: (error) => { - const errorMessage = getMessageFromFetchError(error); - if (errorMessage) { - enqueueSnackbar(errorMessage); - clearUserData(); - clearAuthToken(); - } - }, - }); - if (location.state?.redirectTo) - return ; + useUserFetcher({ + url: `https://hub.pena.digital/user/${userId}`, + userId, + onNewUser: setUser, + onError: (error) => { + const errorMessage = getMessageFromFetchError(error); + if (errorMessage) { + enqueueSnackbar(errorMessage); + clearUserData(); + clearAuthToken(); + } + }, + }); - return ( - <> - - {location.state?.backgroundLocation && ( - - } /> - } /> - } /> - - )} - - } /> - } /> - } /> - } /> - }> - {routeslink.map((e, i) => ( - } /> - ))} + useUserAccountFetcher({ + url: "https://squiz.pena.digital/customer/account", + userId, + onNewUserAccount: setUserAccount, + onError: (error) => { + const errorMessage = getMessageFromFetchError(error); + if (errorMessage) { + enqueueSnackbar(errorMessage); + clearUserData(); + clearAuthToken(); + navigate("/signin"); + } + }, + }); - } /> - } /> - } /> - - - - ); + if (location.state?.redirectTo) + return ; + + return ( + <> + + {location.state?.backgroundLocation && ( + + } /> + } /> + } /> + + )} + + } /> + } /> + } /> + } /> + }> + {routeslink.map((e, i) => ( + } /> + ))} + + } /> + } /> + } /> + + + + ); } diff --git a/src/api/question.ts b/src/api/question.ts index e70b4ccb..56983d76 100644 --- a/src/api/question.ts +++ b/src/api/question.ts @@ -18,7 +18,6 @@ function createQuestion(body: CreateQuestionRequest) { } async function getQuestionList(body?: Partial) { - console.log("body" , body) if (!body?.quiz_id) return null; const response = await makeRequest({ diff --git a/src/pages/ContactFormPage/NewField/ButtonsNewField.tsx b/src/pages/ContactFormPage/NewField/ButtonsNewField.tsx index f70fcea7..3ca2d7e2 100644 --- a/src/pages/ContactFormPage/NewField/ButtonsNewField.tsx +++ b/src/pages/ContactFormPage/NewField/ButtonsNewField.tsx @@ -17,8 +17,6 @@ interface Props { export default function ButtonsNewField ({SSHC, switchState, type}:Props) { const theme = useTheme(); const quiz = useCurrentQuiz() - console.log(quiz) - console.log(type) const buttonSetting: {icon: JSX.Element; title: string; value: string} [] =[ {icon: , title: 'Имя', value: 'name'}, {icon: , title: 'Email', value: 'email'}, diff --git a/src/pages/ContactFormPage/NewField/NewFieldParent.tsx b/src/pages/ContactFormPage/NewField/NewFieldParent.tsx index c4e3ae0c..4dc46078 100644 --- a/src/pages/ContactFormPage/NewField/NewFieldParent.tsx +++ b/src/pages/ContactFormPage/NewField/NewFieldParent.tsx @@ -18,7 +18,6 @@ interface Props { export default function NewFieldParent({ drawerNewFieldHC, defaultValue, placeholderHelp, placeholderField, outerContainerSx: sx, children }: Props) { const quiz = useCurrentQuiz() - console.log({ defaultValue, placeholderHelp, placeholderField, outerContainerSx: sx, children }) return ( @@ -73,7 +72,6 @@ export default function NewFieldParent({ drawerNewFieldHC, defaultValue, placeho { - console.log("click") updateQuiz(quiz.id, (quiz) => { quiz.config.formContact[defaultValue].required = target.checked }) diff --git a/src/pages/ContactFormPage/NewField/SwitchNewField.tsx b/src/pages/ContactFormPage/NewField/SwitchNewField.tsx index 139add09..2a962539 100644 --- a/src/pages/ContactFormPage/NewField/SwitchNewField.tsx +++ b/src/pages/ContactFormPage/NewField/SwitchNewField.tsx @@ -14,7 +14,6 @@ interface Props { export default function SwitchNewField({switchState ='name', drawerNewFieldHC}: Props) { const [SwitchMask, setSwitchMask] = React.useState(false); - console.log(switchState) const SwitchMaskHC = (bool:boolean) => { setSwitchMask(bool) } diff --git a/src/pages/InstallQuiz/InstallQuiz.tsx b/src/pages/InstallQuiz/InstallQuiz.tsx index db89f157..e5ef774d 100644 --- a/src/pages/InstallQuiz/InstallQuiz.tsx +++ b/src/pages/InstallQuiz/InstallQuiz.tsx @@ -48,7 +48,6 @@ type BackgroundType = "text" | "video"; export default function InstallQuiz() { const quiz = useCurrentQuiz() - console.log(quiz) const [display, setDisplay] = React.useState("1"); const handleChange = (event: SelectChangeEvent) => { diff --git a/src/pages/Questions/BranchingMap/CsComponent.tsx b/src/pages/Questions/BranchingMap/CsComponent.tsx index 30db6972..98de15d9 100644 --- a/src/pages/Questions/BranchingMap/CsComponent.tsx +++ b/src/pages/Questions/BranchingMap/CsComponent.tsx @@ -1,6 +1,6 @@ import { useEffect, useLayoutEffect, useRef, useState } from "react"; import Cytoscape from "cytoscape"; -import { Button } from "@mui/material"; +import { Button, Box } from "@mui/material"; import CytoscapeComponent from "react-cytoscapejs"; import popper from "cytoscape-popper"; import { useCurrentQuiz } from "@root/quizes/hooks"; @@ -8,9 +8,10 @@ import { updateRootContentId } from "@root/quizes/actions" import { AnyTypedQuizQuestion } from "@model/questionTypes/shared" import { useQuestionsStore } from "@root/questions/store"; import { deleteQuestion, updateQuestion, getQuestionByContentId, clearRuleForAll, createFrontResult } from "@root/questions/actions"; -import { updateOpenedModalSettingsId, } from "@root/uiTools/actions"; +import { updateCanCreatePublic, updateModalInfoWhyCantCreate, updateOpenedModalSettingsId, } from "@root/uiTools/actions"; import { cleardragQuestionContentId } from "@root/uiTools/actions"; import { withErrorBoundary } from "react-error-boundary"; +import { ProblemIcon } from "@ui_kit/ProblemIcon"; import { storeToNodes } from "./helper"; @@ -115,6 +116,7 @@ interface Props { } + function CsComponent({ modalQuestionParentContentId, modalQuestionTargetContentId, @@ -124,7 +126,7 @@ function CsComponent({ }: Props) { const quiz = useCurrentQuiz(); - const { dragQuestionContentId, desireToOpenABranchingModal } = useUiTools() + const { dragQuestionContentId, desireToOpenABranchingModal, canCreatePublic } = useUiTools() const trashQuestions = useQuestionsStore().questions const questions = trashQuestions.filter((question) => question.type !== "result" && question.type !== null) const [startCreate, setStartCreate] = useState(""); @@ -136,6 +138,13 @@ function CsComponent({ const crossesContainer = useRef(null); const gearsContainer = useRef(null); + + useEffect(() => { + return () => { + // if (!canCreatePublic) updateModalInfoWhyCantCreate(true) + } + }, []); + useLayoutEffect(() => { const cy = cyRef?.current if (desireToOpenABranchingModal) { @@ -148,8 +157,8 @@ function CsComponent({ }, [desireToOpenABranchingModal]) useLayoutEffect(() => { updateOpenedModalSettingsId() - // updateRootContentId(quiz.id, "") - // clearRuleForAll() + // updateRootContentId(quiz.id, "") + // clearRuleForAll() }, []) useEffect(() => { if (modalQuestionTargetContentId.length !== 0 && modalQuestionParentContentId.length !== 0) { @@ -160,7 +169,7 @@ function CsComponent({ }, [modalQuestionTargetContentId]) const addNode = ({ parentNodeContentId, targetNodeContentId }: { parentNodeContentId: string, targetNodeContentId?: string }) => { - + //запрещаем работу родителя-ребенка если это один и тот же вопрос if (parentNodeContentId === targetNodeContentId) return @@ -169,7 +178,7 @@ function CsComponent({ const parentNodeChildren = cy?.$('edge[source = "' + parentNodeContentId + '"]')?.length //если есть инфо о выбранном вопросе из модалки - берём родителя из инфо модалки. Иначе из значения дропа const targetQuestion = { ...getQuestionByContentId(targetNodeContentId || dragQuestionContentId) } as AnyTypedQuizQuestion - if (Object.keys(targetQuestion).length !== 0 && parentNodeContentId && parentNodeChildren !== undefined) { + if (Object.keys(targetQuestion).length !== 0 && parentNodeContentId && parentNodeChildren !== undefined) { clearDataAfterAddNode({ parentNodeContentId, targetQuestion, parentNodeChildren }) cy?.data('changed', true) createFrontResult(quiz.backendId, targetQuestion.content.id) @@ -188,7 +197,6 @@ function CsComponent({ } ]) cy?.layout(lyopts).run() - console.log(es) cy?.center(es) } else { enqueueSnackbar("Добавляемый вопрос не найден") @@ -203,7 +211,6 @@ function CsComponent({ //смотрим не добавлен ли родителю result. Если да - убираем его. Веточкам result не нужен trashQuestions.forEach((targetQuestion) => { if (targetQuestion.type === "result" && targetQuestion.content.rule.parentId === parentQuestion.content.id) { - console.log('deleteQ', targetQuestion.id) deleteQuestion(targetQuestion.id); } }) @@ -228,7 +235,6 @@ function CsComponent({ const removeNode = ({ targetNodeContentId }: { targetNodeContentId: string }) => { - console.log("старт удаление") const deleteNodes = [] as string[] const deleteEdges: any = [] const cy = cyRef?.current @@ -272,8 +278,8 @@ function CsComponent({ const parentQuestionContentId = cy?.$('edge[target = "' + targetNodeContentId + '"]')?.toArray()?.[0]?.data()?.source if (targetNodeContentId && parentQuestionContentId) { -if (cy?.edges(`[source="${parentQuestionContentId}"]`).length === 0) - createFrontResult(quiz.backendId, parentQuestionContentId) + if (cy?.edges(`[source="${parentQuestionContentId}"]`).length === 0) + createFrontResult(quiz.backendId, parentQuestionContentId) clearDataAfterRemoveNode({ targetQuestionContentId: targetNodeContentId, parentQuestionContentId }) cy?.remove(cy?.$('#' + targetNodeContentId)).layout(lyopts).run() } @@ -640,36 +646,35 @@ if (cy?.edges(`[source="${parentQuestionContentId}"]`).length === 0) return crossElement; }, }); -let gearsPopper = null + let gearsPopper = null if (node.data().root !== true) { - gearsPopper = node.popper({ - popper: { - placement: "left", - modifiers: [{ name: "flip", options: { boundary: node } }], - }, - content: ([item]) => { - const itemId = item.id(); + gearsPopper = node.popper({ + popper: { + placement: "left", + modifiers: [{ name: "flip", options: { boundary: node } }], + }, + content: ([item]) => { + const itemId = item.id(); - const itemElement = gearsContainer.current?.querySelector( - `.popper-gear[data-id='${itemId}']` - ); - if (itemElement) { - return itemElement; - } + const itemElement = gearsContainer.current?.querySelector( + `.popper-gear[data-id='${itemId}']` + ); + if (itemElement) { + return itemElement; + } - const gearElement = document.createElement("div"); - gearElement.classList.add("popper-gear"); - gearElement.setAttribute("data-id", item.id()); - gearElement.style.zIndex = "1" - gearsContainer.current?.appendChild(gearElement); - gearElement.addEventListener("mouseup", (e) => { - console.log("up") - updateOpenedModalSettingsId(item.id()) - }); + const gearElement = document.createElement("div"); + gearElement.classList.add("popper-gear"); + gearElement.setAttribute("data-id", item.id()); + gearElement.style.zIndex = "1" + gearsContainer.current?.appendChild(gearElement); + gearElement.addEventListener("mouseup", (e) => { + updateOpenedModalSettingsId(item.id()) + }); - return gearElement; - }, - }); + return gearElement; + }, + }); } const update = async () => { await plusesPopper.update(); @@ -786,23 +791,27 @@ let gearsPopper = null return ( <> - + }} + > + Выровнять + + updateModalInfoWhyCantCreate(true)} /> + + - {/* - */} ); }; diff --git a/src/pages/Questions/BranchingMap/FirstNodeField.tsx b/src/pages/Questions/BranchingMap/FirstNodeField.tsx index 5bae72c1..6c988b2c 100644 --- a/src/pages/Questions/BranchingMap/FirstNodeField.tsx +++ b/src/pages/Questions/BranchingMap/FirstNodeField.tsx @@ -18,7 +18,6 @@ export const FirstNodeField = ({ setOpenedModalQuestions, modalQuestionTargetCon useLayoutEffect(() => { updateOpenedModalSettingsId() - console.log("first render firstComponent") updateRootContentId(quiz.id, "") clearRuleForAll() }, []) diff --git a/src/pages/Questions/BranchingPanel/index.tsx b/src/pages/Questions/BranchingPanel/index.tsx index 61e03f47..bcb6fdd6 100644 --- a/src/pages/Questions/BranchingPanel/index.tsx +++ b/src/pages/Questions/BranchingPanel/index.tsx @@ -77,7 +77,7 @@ export const BranchingPanel = (sx?: SxProps) => { /> - Логика ветвления + Логика ветвления Настройте связи между вопросами diff --git a/src/pages/Questions/ButtonsOptions.tsx b/src/pages/Questions/ButtonsOptions.tsx index a3d015db..66cdef0a 100644 --- a/src/pages/Questions/ButtonsOptions.tsx +++ b/src/pages/Questions/ButtonsOptions.tsx @@ -106,7 +106,6 @@ export default function ButtonsOptions({ deleteQuestion(question.id); } else { - console.log("удаляю безтипогово"); deleteQuestion(question.id); } }; @@ -149,7 +148,6 @@ export default function ButtonsOptions({ title: "Ветвление", value: "branching", myFunc: (question) => { - console.log("buttons opiums") updateOpenBranchingPanel(true); updateDesireToOpenABranchingModal(question.content.id); } diff --git a/src/pages/Questions/ButtonsOptionsAndPict.tsx b/src/pages/Questions/ButtonsOptionsAndPict.tsx index 4b5528c4..e4fbae65 100644 --- a/src/pages/Questions/ButtonsOptionsAndPict.tsx +++ b/src/pages/Questions/ButtonsOptionsAndPict.tsx @@ -107,7 +107,6 @@ export default function ButtonsOptionsAndPict({ deleteQuestion(question.id); } else { - console.log("удаляю безтипогово"); deleteQuestion(question.id); } }; @@ -254,7 +253,6 @@ export default function ButtonsOptionsAndPict({ onMouseEnter={() => setButtonHover("branching")} onMouseLeave={() => setButtonHover("")} onClick={() => { - console.log("buttonsOptions") updateOpenBranchingPanel(true); updateDesireToOpenABranchingModal(question.content.id); }} diff --git a/src/pages/Questions/DraggableList/QuestionPageCard.tsx b/src/pages/Questions/DraggableList/QuestionPageCard.tsx index 7c947710..bfa3d59e 100644 --- a/src/pages/Questions/DraggableList/QuestionPageCard.tsx +++ b/src/pages/Questions/DraggableList/QuestionPageCard.tsx @@ -123,7 +123,6 @@ export default function QuestionsPageCard({ question, draggableProps, isDragging deleteQuestion(question.id); } else { - console.log("удаляю безтипогово"); deleteQuestion(question.id); } }; diff --git a/src/pages/Questions/Form/FormDraggableList/QuestionPageCard.tsx b/src/pages/Questions/Form/FormDraggableList/QuestionPageCard.tsx index d4f140f5..14be7e7b 100644 --- a/src/pages/Questions/Form/FormDraggableList/QuestionPageCard.tsx +++ b/src/pages/Questions/Form/FormDraggableList/QuestionPageCard.tsx @@ -51,6 +51,7 @@ export default function QuestionsPageCard({ question, questionIndex, draggablePr }); }, 200); + console.log(question) return ( <> setTitle(target.value)} sx={{ width: "100%" }} InputProps={{ @@ -224,4 +225,4 @@ const IconAndrom = (questionType: QuestionType | null) => { default: return ; } -}; +}; \ No newline at end of file diff --git a/src/pages/Questions/Form/FormDraggableList/index.tsx b/src/pages/Questions/Form/FormDraggableList/index.tsx index 77c01d28..058e9e53 100644 --- a/src/pages/Questions/Form/FormDraggableList/index.tsx +++ b/src/pages/Questions/Form/FormDraggableList/index.tsx @@ -6,8 +6,7 @@ import FormDraggableListItem from "./FormDraggableListItem"; import { useQuestions } from "@root/questions/hooks"; export const FormDraggableList = () => { - const { questions } = useQuestions(); - + const questions = useQuestions().questions.filter((q) => q.type !== "result"); const onDragEnd = ({ destination, source }: DropResult) => { if (destination) reorderQuestions(source.index, destination.index); }; diff --git a/src/pages/Questions/Form/FormQuestionsPage.tsx b/src/pages/Questions/Form/FormQuestionsPage.tsx index baca3a95..323d79cc 100644 --- a/src/pages/Questions/Form/FormQuestionsPage.tsx +++ b/src/pages/Questions/Form/FormQuestionsPage.tsx @@ -13,6 +13,7 @@ export default function FormQuestionsPage() { const quiz = useCurrentQuiz(); if (!quiz) return null; + console.log("Анкета") return ( <> diff --git a/src/pages/Questions/QuestionSwitchWindowTool.tsx b/src/pages/Questions/QuestionSwitchWindowTool.tsx index f55e3e2a..5988ecd0 100644 --- a/src/pages/Questions/QuestionSwitchWindowTool.tsx +++ b/src/pages/Questions/QuestionSwitchWindowTool.tsx @@ -14,8 +14,6 @@ export const QuestionSwitchWindowTool = () => { 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 ( diff --git a/src/pages/Questions/SwitchBranchingPanel/index.tsx b/src/pages/Questions/SwitchBranchingPanel/index.tsx index 11eff218..bd20f70b 100644 --- a/src/pages/Questions/SwitchBranchingPanel/index.tsx +++ b/src/pages/Questions/SwitchBranchingPanel/index.tsx @@ -12,7 +12,7 @@ import { useUiTools } from "@root/uiTools/store"; export const SwitchBranchingPanel = () => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down(660)); - const isTablet = useMediaQuery(theme.breakpoints.down(1000)); + const isTablet = useMediaQuery(theme.breakpoints.down(1446)); const {openBranchingPanel} = useUiTools() const ref = useRef() diff --git a/src/pages/Questions/UploadImage/UploadImageModal.tsx b/src/pages/Questions/UploadImage/UploadImageModal.tsx index d722e81f..a0f3bb06 100644 --- a/src/pages/Questions/UploadImage/UploadImageModal.tsx +++ b/src/pages/Questions/UploadImage/UploadImageModal.tsx @@ -42,7 +42,6 @@ export const UploadImageModal: React.FC = ({ const acceptedFormats = accept ? accept.map((format) => "." + format).join(", ") : ""; - console.log(acceptedFormats); return ( { } export const ResultCard = ({ resultContract, resultData }: Props) => { - console.log("resultData", resultData) const quizQid = useCurrentQuiz()?.qid; const theme = useTheme(); diff --git a/src/pages/ViewPublicationPage/Footer.tsx b/src/pages/ViewPublicationPage/Footer.tsx index 720dd000..8a1f2dea 100644 --- a/src/pages/ViewPublicationPage/Footer.tsx +++ b/src/pages/ViewPublicationPage/Footer.tsx @@ -78,7 +78,6 @@ export const Footer = ({ setCurrentQuestion, question, setShowContactForm, setSh }, [question, answers]); const showResult = (nextQuestion) => { - console.log(nextQuestion); if (nextQuestion && quiz?.config.resultInfo.when === "before") { setShowResultForm(true); @@ -154,14 +153,9 @@ export const Footer = ({ setCurrentQuestion, question, setShowContactForm, setSh const questionIndex = questions.findIndex(({ id }) => id === question.id); const nextQuestion = questions[questionIndex + 1]; - console.log("questionIndex ", questionIndex); - console.log(nextQuestion); - console.log(questions); if (nextQuestion && nextQuestion.type !== "result") { - console.log("следующий вопрос результирующий ", nextQuestion.type === "result"); setCurrentQuestion(nextQuestion); } else { - console.log("следующий вопрос результирующий ", nextQuestion.type === "result"); showResult(nextQuestion); } @@ -173,7 +167,6 @@ export const Footer = ({ setCurrentQuestion, question, setShowContactForm, setSh if (nextQuestionId) { const nextQuestion = getQuestionByContentId(nextQuestionId); - console.log(nextQuestion); if (nextQuestion?.type && nextQuestion.type !== "result") { setCurrentQuestion(nextQuestion); return; diff --git a/src/pages/ViewPublicationPage/Question.tsx b/src/pages/ViewPublicationPage/Question.tsx index 0832f7cf..ff251329 100644 --- a/src/pages/ViewPublicationPage/Question.tsx +++ b/src/pages/ViewPublicationPage/Question.tsx @@ -43,7 +43,8 @@ const QUESTIONS_MAP: any = { export const Question = ({ questions }: QuestionProps) => { const quiz = useCurrentQuiz(); - const [currentQuestion, setCurrentQuestion] = useState(); + const [currentQuestion, setCurrentQuestion] = + useState(); const [showContactForm, setShowContactForm] = useState(false); const [showResultForm, setShowResultForm] = useState(false); @@ -61,9 +62,9 @@ export const Question = ({ questions }: QuestionProps) => { if (!currentQuestion) return <>не смог отобразить вопрос; - const QuestionComponent = QUESTIONS_MAP[currentQuestion.type as Exclude]; + const QuestionComponent = + QUESTIONS_MAP[currentQuestion.type as Exclude]; - console.log("showResultForm " , showResultForm) return ( {!showContactForm && !showResultForm && ( diff --git a/src/pages/ViewPublicationPage/ResultForm.tsx b/src/pages/ViewPublicationPage/ResultForm.tsx index 70c30671..9dd57782 100644 --- a/src/pages/ViewPublicationPage/ResultForm.tsx +++ b/src/pages/ViewPublicationPage/ResultForm.tsx @@ -30,17 +30,13 @@ export const ResultForm = ({ ); - console.log(currentQuestion) - console.log(resultQuestion - ) - console.log(questions) - console.log(quiz?.config.resultInfo.when) const followNextForm = () => { setShowResultForm(false); setShowContactForm(true); }; + if (resultQuestion === undefined) return <> return ( { className="quiz-preview-draghandle" sx={{ height: "100vh", + width: "100vw", background: quiz.config.startpageType === "expanded" ? quiz.config.startpage.position === "left" @@ -82,6 +83,7 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => { ? "linear-gradient(180deg,transparent,#272626)" : "linear-gradient(270deg,#272626,transparent)" : "", + color: quiz.config.startpageType === "expanded" ? "white" : "black", }} > @@ -142,6 +144,9 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => { fontStyle: "normal", fontStretch: "normal", lineHeight: "1.2", + overflowWrap: "break-word", + width: "100%", + textAlign: quiz.config.startpageType === "centered" ? "center" : "-moz-initial", }} > {quiz.name} @@ -150,6 +155,9 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => { sx={{ fontSize: "16px", m: "16px 0", + overflowWrap: "break-word", + width: "100%", + textAlign: quiz.config.startpageType === "centered" ? "center" : "-moz-initial", }} > {quiz.config.startpage.description} @@ -172,7 +180,7 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => { - + {quiz.config.info.clickable ? ( isMobileDevice ? ( @@ -192,7 +200,9 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => { {quiz.config.info.phonenumber} )} - {quiz.config.info.law} + + {quiz.config.info.law} + @@ -329,7 +339,16 @@ function QuizPreviewLayoutByType({ }} > {quizHeaderBlock} - {backgroundBlock && {backgroundBlock}} + {backgroundBlock && ( + + {backgroundBlock} + + )} {quizMainBlock} ); diff --git a/src/pages/ViewPublicationPage/index.tsx b/src/pages/ViewPublicationPage/index.tsx index 5b71d6b6..a84851a3 100644 --- a/src/pages/ViewPublicationPage/index.tsx +++ b/src/pages/ViewPublicationPage/index.tsx @@ -52,9 +52,11 @@ export const ViewPage = () => { questions.filter(({ type }) => type) as AnyTypedQuizQuestion[] ).sort((previousItem, item) => previousItem.page - item.page); - console.log("visualStartPage ", visualStartPage); + + console.log(questions) + if (visualStartPage === undefined) return <>; - if (questions.length === 0) return + if (questions.length === 0 || (questions.length === 1 && questions[0].type === "result")) return return ( {!visualStartPage ? ( diff --git a/src/pages/ViewPublicationPage/questions/Varimg.tsx b/src/pages/ViewPublicationPage/questions/Varimg.tsx index f4fb781b..5e07766b 100644 --- a/src/pages/ViewPublicationPage/questions/Varimg.tsx +++ b/src/pages/ViewPublicationPage/questions/Varimg.tsx @@ -31,8 +31,6 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => { ({ id }) => answer === id ); - console.log(currentQuestion) - return ( {currentQuestion.title} diff --git a/src/pages/startPage/EditPage.tsx b/src/pages/startPage/EditPage.tsx index 2cd821bd..11f091bb 100755 --- a/src/pages/startPage/EditPage.tsx +++ b/src/pages/startPage/EditPage.tsx @@ -1,5 +1,5 @@ import { quizApi } from "@api/quiz"; -import { devlog } from "@frontend/kitui"; +import { LogoutButton } from "@ui_kit/LogoutButton"; import BackArrowIcon from "@icons/BackArrowIcon"; import { Burger } from "@icons/Burger"; import EyeIcon from "@icons/EyeIcon"; @@ -16,7 +16,7 @@ import { useMediaQuery, useTheme, } from "@mui/material"; -import {decrementCurrentStep, resetEditConfig, setQuizes, updateQuiz} from "@root/quizes/actions"; +import { decrementCurrentStep, resetEditConfig, setQuizes, updateQuiz } from "@root/quizes/actions"; import { useCurrentQuiz } from "@root/quizes/hooks"; import { useQuizStore } from "@root/quizes/store"; import CustomAvatar from "@ui_kit/Header/Avatar"; @@ -30,9 +30,10 @@ import { enqueueSnackbar } from "notistack"; import React, { useEffect, useLayoutEffect, useState } from "react"; import { Link, useNavigate } from "react-router-dom"; import useSWR from "swr"; +import { useDebouncedCallback } from "use-debounce"; import { SidebarMobile } from "./Sidebar/SidebarMobile"; import { cleanQuestions, setQuestions } from "@root/questions/actions"; -import { updateOpenBranchingPanel } from "@root/uiTools/actions"; +import { updateOpenBranchingPanel, updateCanCreatePublic, updateModalInfoWhyCantCreate } from "@root/uiTools/actions"; import { BranchingPanel } from "../Questions/BranchingPanel"; import { useQuestionsStore } from "@root/questions/store"; import { useQuizes } from "@root/quizes/hooks"; @@ -40,10 +41,16 @@ import { questionApi } from "@api/question"; import { useUiTools } from "@root/uiTools/store"; import Logotip from "../Landing/images/icons/QuizLogo"; +import { clearUserData } from "@root/user"; +import { clearAuthToken } from "@frontend/kitui"; +import { logout } from "@api/auth"; +import { AnyTypedQuizQuestion } from "@model/questionTypes/shared"; +import { ModalInfoWhyCantCreate } from "./ModalInfoWhyCantCreate"; export default function EditPage() { const quiz = useCurrentQuiz(); const { editQuizId } = useQuizStore(); + const { questions } = useQuestionsStore(); useEffect(() => { const getData = async () => { @@ -56,7 +63,7 @@ export default function EditPage() { getData(); }, []); - const { openBranchingPanel } = useUiTools(); + const { openBranchingPanel, whyCantCreatePublic, canCreatePublic } = useUiTools(); const theme = useTheme(); const navigate = useNavigate(); const currentStep = useQuizStore((state) => state.currentStep); @@ -74,11 +81,61 @@ export default function EditPage() { () => () => { resetEditConfig(); cleanQuestions(); + updateModalInfoWhyCantCreate(false) }, [] ); - console.log(currentStep) - console.log(quizConfig) + + + + const updateQuestionHint = useDebouncedCallback((questions: AnyTypedQuizQuestion[]) => { + + const problems: any = {} + + questions.forEach((question) => { + //Если не участвует в ветвлении, или безтиповый, или резулт - он нам не интересен + if (question.type === null + || question.type === "result" + || question.content.rule.parentId.length === 0) return + + //если есть дети, но нет дефолта - логическая ошибка. Так нельзя + if (question.content.rule.children.length > 0 && question.content.rule.default.length === 0) { + problems[question.content.id] = { + name: question.title, + problems: ["Не выбран дефолтный вопрос"] + } + } + + }) + + useUiTools.setState({ whyCantCreatePublic: problems }) + if (Object.keys(problems).length > 0) { + updateQuiz(quiz?.id, (state) => { state.status = "stop" }) + updateCanCreatePublic(false) + } else { + updateCanCreatePublic(true) + } + + + }, 600); + + + useEffect(() => { + updateQuestionHint(questions) + }, [questions]); + + + async function handleLogoutClick() { + const [, logoutError] = await logout(); + + if (logoutError) { + return enqueueSnackbar(logoutError); + } + + clearAuthToken(); + clearUserData(); + navigate("/"); + } if (!quizConfig) return <> return ( @@ -99,7 +156,7 @@ export default function EditPage() { }} > - {isMobile ? : } + {isMobile ? : } ) : ( - + + + )} ) : ( @@ -196,6 +255,7 @@ export default function EditPage() { width: "36px", }} /> + )} @@ -230,137 +290,144 @@ export default function EditPage() { )} - - {[1].includes(currentStep) && !openBranchingPanel && quizConfig.type !== "form" && ( - + {[1].includes(currentStep) && !openBranchingPanel && quizConfig.type !== "form" && ( + + updateOpenBranchingPanel(e.target.checked)} sx={{ - display: "flex", - alignItems: "center", - gap: "15px", - padding: "18px", - background: "#fff", - borderRadius: "12px", - boxShadow: "0px 10px 30px #e7e7e7", + 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, + }), + }, + }} + /> + + Логика ветвления + + + )} + + {!canCreatePublic && quiz.config.type !== "form" ? + + : + + - ) : ( - - - - )} + Тестовый просмотр + + + } - - - {quiz?.status === "start" && https://hbpn.link/{quiz.qid} } - + + {quiz?.status === "start" && https://hbpn.link/{quiz.qid} + } + + ); } diff --git a/src/pages/startPage/ModalInfoWhyCantCreate.tsx b/src/pages/startPage/ModalInfoWhyCantCreate.tsx new file mode 100644 index 00000000..26e38506 --- /dev/null +++ b/src/pages/startPage/ModalInfoWhyCantCreate.tsx @@ -0,0 +1,49 @@ +import { Box, Modal, Typography, Divider } from "@mui/material" + +import { useUiTools } from "@root/uiTools/store"; +import { updateModalInfoWhyCantCreate } from "@root/uiTools/actions"; +import { useLayoutEffect } from "react"; + +export const ModalInfoWhyCantCreate = () => { + + const { whyCantCreatePublic, openModalInfoWhyCantCreate } = useUiTools(); + + return ( + updateModalInfoWhyCantCreate(false)} + > + + { + Object.values(whyCantCreatePublic).map((data) => { + return ( + + У вопроса "{data.name}" + { + data.problems.map((problem) => {problem}) + } + + + ) + }) + } + + + ) +} \ No newline at end of file diff --git a/src/pages/startPage/Restore.tsx b/src/pages/startPage/Restore.tsx index 0940e14b..31cc8ad3 100644 --- a/src/pages/startPage/Restore.tsx +++ b/src/pages/startPage/Restore.tsx @@ -41,7 +41,6 @@ export const Restore: FC = () => { initialValues, validationSchema, onSubmit: (values) => { - console.log(values); }, }); diff --git a/src/pages/startPage/StartPageSettings.tsx b/src/pages/startPage/StartPageSettings.tsx index f6fa0f0f..fa1cc2d4 100755 --- a/src/pages/startPage/StartPageSettings.tsx +++ b/src/pages/startPage/StartPageSettings.tsx @@ -9,16 +9,16 @@ import LayoutStandartIcon from "@icons/LayoutStandartIcon"; import MobilePhoneIcon from "@icons/MobilePhoneIcon"; import { QuizStartpageType } from "@model/quizSettings"; import { - Box, - Button, - Checkbox, - FormControl, - FormControlLabel, - MenuItem, - Select, - Typography, - useMediaQuery, - useTheme + Box, + Button, + Checkbox, + FormControl, + FormControlLabel, + MenuItem, + Select, + Typography, + useMediaQuery, + useTheme, } from "@mui/material"; import { incrementCurrentStep, updateQuiz, uploadQuizImage } from "@root/quizes/actions"; import { useCurrentQuiz } from "@root/quizes/hooks"; @@ -35,733 +35,736 @@ import SelectableIconButton from "./SelectableIconButton"; import { DropZone } from "./dropZone"; import Extra from "./extra"; - const designTypes = [ - [ - "standard", - (color: string) => , - "Standard", - ], - [ - "expanded", - (color: string) => , - "Expanded", - ], - [ - "centered", - (color: string) => , - "Centered", - ], + ["standard", (color: string) => , "Standard"], + ["expanded", (color: string) => , "Expanded"], + ["centered", (color: string) => , "Centered"], ] as const; // type DesignType = typeof designTypes[number][0]; - export default function StartPageSettings() { - const theme = useTheme(); - const isSmallMonitor = useMediaQuery(theme.breakpoints.down(1500)); - const isTablet = useMediaQuery(theme.breakpoints.down(950)); - const quiz = useCurrentQuiz(); - const [formState, setFormState] = useState<"design" | "content">("design"); - const [mobileVersion, setMobileVersion] = useState(false); + const theme = useTheme(); + const isSmallMonitor = useMediaQuery(theme.breakpoints.down(1500)); + const isTablet = useMediaQuery(theme.breakpoints.down(950)); + const quiz = useCurrentQuiz(); + const [formState, setFormState] = useState<"design" | "content">("design"); + const [mobileVersion, setMobileVersion] = useState(false); - if (!quiz) return null; + if (!quiz) return null; - const MobileVersionHC = (bool: boolean) => { - setMobileVersion(bool); - }; + const MobileVersionHC = (bool: boolean) => { + setMobileVersion(bool); + }; - const designType = quiz?.config?.startpageType; + const designType = quiz?.config?.startpageType; - const favIconDropZoneElement = ( - { - const resizedImage = await resizeFavIcon(file); - uploadQuizImage(quiz.id, resizedImage, (quiz, url) => { - quiz.config.startpage.favIcon = url; - }); - }} - onDeleteClick={() => { - updateQuiz(quiz.id, quiz => { - quiz.config.startpage.favIcon = null; - }); - }} - /> - ); + const favIconDropZoneElement = ( + { + const resizedImage = await resizeFavIcon(file); + uploadQuizImage(quiz.id, resizedImage, (quiz, url) => { + quiz.config.startpage.favIcon = url; + }); + }} + onDeleteClick={() => { + updateQuiz(quiz.id, (quiz) => { + quiz.config.startpage.favIcon = null; + }); + }} + /> + ); - return ( - <> + return ( + <> + + Стартовая страница + + {isSmallMonitor && ( + + - - - )} - + + + )} + + {(!isSmallMonitor || (isSmallMonitor && formState === "design")) && ( + + - {(!isSmallMonitor || (isSmallMonitor && formState === "design")) && ( - - - Дизайн - - - - - - Фон - - - updateQuiz(quiz.id, quiz => { - quiz.config.startpage.background.type = "image"; - })} - > - Изображение - - updateQuiz(quiz.id, quiz => { - quiz.config.startpage.background.type = "video"; - })} - > - Видео - - - - - - - Изображение - - { - uploadQuizImage(quiz.id, file, (quiz, url) => { - quiz.config.startpage.background.desktop = url; - quiz.config.startpage.background.originalDesktop = url; - }); - }} - onImageSaveClick={file => { - uploadQuizImage(quiz.id, file, (quiz, url) => { - quiz.config.startpage.background.desktop = url; - }); - }} - onDeleteClick={() => { - updateQuiz(quiz.id, quiz => { - quiz.config.startpage.background.desktop = null; - }); - }} - /> - - - - - - - - - updateQuiz(quiz.id, quiz => { - quiz.config.startpage.background.video = e.target.value; - })} - /> - - - - {designType !== "centered" && - <> - - Расположение элементов - - - updateQuiz(quiz.id, quiz => { - quiz.config.startpage.position = "left"; - })} - isActive={quiz.config.startpage.position === "left"} - Icon={AlignLeftIcon} - /> - updateQuiz(quiz.id, quiz => { - quiz.config.startpage.position = "center"; - })} - isActive={quiz.config.startpage.position === "center"} - Icon={AlignCenterIcon} - sx={{ display: designType === "standard" ? "none" : "flex" }} - /> - updateQuiz(quiz.id, quiz => { - quiz.config.startpage.position = "right"; - })} - isActive={quiz.config.startpage.position === "right"} - Icon={AlignRightIcon} - /> - - - - } - {(isTablet || !isSmallMonitor) && ( - <> - - - Логотип - - { - uploadQuizImage(quiz.id, file, (quiz, url) => { - quiz.config.startpage.logo = url; - quiz.config.startpage.originalLogo = url; - }); - }} - onImageSaveClick={file => { - uploadQuizImage(quiz.id, file, (quiz, url) => { - quiz.config.startpage.logo = url; - }); - }} - onDeleteClick={() => { - updateQuiz(quiz.id, quiz => { - quiz.config.startpage.logo = null; - }); - }} - /> - - - - Favicon - - {favIconDropZoneElement} - - )} - - )} - {/*Правая сторона*/} - - {!isTablet && isSmallMonitor && formState === "design" && ( - <> - - - Логотип - - { - uploadQuizImage(quiz.id, file, (quiz, url) => { - quiz.config.startpage.logo = url; - quiz.config.startpage.originalLogo = url; - }); - }} - onImageSaveClick={file => { - uploadQuizImage(quiz.id, file, (quiz, url) => { - quiz.config.startpage.logo = url; - }); - }} - onDeleteClick={() => { - updateQuiz(quiz.id, quiz => { - quiz.config.startpage.logo = null; - }); - }} - /> - - - - Favicon - - {favIconDropZoneElement} - - )} - {(!isSmallMonitor || (isSmallMonitor && formState === "content")) && ( - <> - - Заголовок - - updateQuiz(quiz.id, quiz => { - quiz.name = e.target.value; - })} - /> - - Текст - - updateQuiz(quiz.id, quiz => { - quiz.config.startpage.description = e.target.value; - })} - /> - - Текст кнопки - - updateQuiz(quiz.id, quiz => { - quiz.config.startpage.button = e.target.value; - })} - /> - - Телефон - - updateQuiz(quiz.id, quiz => { - quiz.config.info.phonenumber = e.target.value; - })} - /> - updateQuiz(quiz.id, quiz => { - quiz.config.info.clickable = e.target.checked; - })} - /> - - Название или слоган компании - - updateQuiz(quiz.id, quiz => { - quiz.config.info.orgname = e.target.value; - })} - /> - - Сайт - - updateQuiz(quiz.id, quiz => { - quiz.config.info.site = e.target.value; - })} - /> - - Юридическая информация - - updateQuiz(quiz.id, quiz => { - quiz.config.info.law = e.target.value; - })} - /> - - - )} - - - {isSmallMonitor && ( - - {formState === "content" && ( - - )} - {formState === "design" && ( - - )} - - )} - + + + + + Фон + + + + updateQuiz(quiz.id, (quiz) => { + quiz.config.startpage.background.type = "image"; + }) + } + > + Изображение + + + updateQuiz(quiz.id, (quiz) => { + quiz.config.startpage.background.type = "video"; + }) + } + > + Видео + - {createPortal(, document.body)} - - ); + + + + + Изображение + + { + uploadQuizImage(quiz.id, file, (quiz, url) => { + quiz.config.startpage.background.desktop = url; + quiz.config.startpage.background.originalDesktop = url; + }); + }} + onImageSaveClick={(file) => { + uploadQuizImage(quiz.id, file, (quiz, url) => { + quiz.config.startpage.background.desktop = url; + }); + }} + onDeleteClick={() => { + updateQuiz(quiz.id, (quiz) => { + quiz.config.startpage.background.desktop = null; + }); + }} + /> + + + + + + + + updateQuiz(quiz.id, (quiz) => { + quiz.config.startpage.background.video = e.target.value; + }) + } + /> + + + {designType !== "centered" && ( + <> + + Расположение элементов + + + + updateQuiz(quiz.id, (quiz) => { + quiz.config.startpage.position = "left"; + }) + } + isActive={quiz.config.startpage.position === "left"} + Icon={AlignLeftIcon} + /> + + updateQuiz(quiz.id, (quiz) => { + quiz.config.startpage.position = "center"; + }) + } + isActive={quiz.config.startpage.position === "center"} + Icon={AlignCenterIcon} + sx={{ display: designType === "standard" ? "none" : "flex" }} + /> + + updateQuiz(quiz.id, (quiz) => { + quiz.config.startpage.position = "right"; + }) + } + isActive={quiz.config.startpage.position === "right"} + Icon={AlignRightIcon} + /> + + + )} + {(isTablet || !isSmallMonitor) && ( + <> + + + Логотип + + { + uploadQuizImage(quiz.id, file, (quiz, url) => { + quiz.config.startpage.logo = url; + quiz.config.startpage.originalLogo = url; + }); + }} + onImageSaveClick={(file) => { + uploadQuizImage(quiz.id, file, (quiz, url) => { + quiz.config.startpage.logo = url; + }); + }} + onDeleteClick={() => { + updateQuiz(quiz.id, (quiz) => { + quiz.config.startpage.logo = null; + }); + }} + /> + + + + Favicon + + {favIconDropZoneElement} + + )} + + )} + {/*Правая сторона*/} + + {!isTablet && isSmallMonitor && formState === "design" && ( + <> + + + Логотип + + { + uploadQuizImage(quiz.id, file, (quiz, url) => { + quiz.config.startpage.logo = url; + quiz.config.startpage.originalLogo = url; + }); + }} + onImageSaveClick={(file) => { + uploadQuizImage(quiz.id, file, (quiz, url) => { + quiz.config.startpage.logo = url; + }); + }} + onDeleteClick={() => { + updateQuiz(quiz.id, (quiz) => { + quiz.config.startpage.logo = null; + }); + }} + /> + + + + Favicon + + {favIconDropZoneElement} + + )} + {(!isSmallMonitor || (isSmallMonitor && formState === "content")) && ( + <> + + Заголовок + + + updateQuiz(quiz.id, (quiz) => { + quiz.name = e.target.value; + }) + } + maxLength={40} + /> + + Текст + + + updateQuiz(quiz.id, (quiz) => { + quiz.config.startpage.description = e.target.value; + }) + } + maxLength={70} + /> + + Текст кнопки + + + updateQuiz(quiz.id, (quiz) => { + quiz.config.startpage.button = e.target.value; + }) + } + maxLength={15} + /> + + Телефон + + + updateQuiz(quiz.id, (quiz) => { + quiz.config.info.phonenumber = e.target.value; + }) + } + maxLength={20} + /> + + updateQuiz(quiz.id, (quiz) => { + quiz.config.info.clickable = e.target.checked; + }) + } + /> + + Название или слоган компании + + + updateQuiz(quiz.id, (quiz) => { + quiz.config.info.orgname = e.target.value; + }) + } + maxLength={25} + /> + + Сайт + + + updateQuiz(quiz.id, (quiz) => { + quiz.config.info.site = e.target.value; + }) + } + maxLength={25} + /> + + Юридическая информация + + + updateQuiz(quiz.id, (quiz) => { + quiz.config.info.law = e.target.value; + }) + } + maxLength={45} + /> + + + )} + + + {isSmallMonitor && ( + + {formState === "content" && ( + + )} + {formState === "design" && ( + + )} + + )} + + + Отключить стартовую страницу + + } + checkedIcon={ + + } + sx={{ + borderRadius: 0, + padding: 0, + }} + onChange={(e) => + updateQuiz(quiz.id, (quiz) => { + quiz.config.noStartPage = e.target.checked; + }) + } + checked={quiz.config.noStartPage} + /> + } + label="" + sx={{ + color: theme.palette.brightPurple.main, + margin: "0", + userSelect: "none", + justifyContent: "flex-end", + }} + /> + + + {createPortal(, document.body)} + + ); } function IconCheck() { - return ( - - ); + return ( + + ); } diff --git a/src/stores/questions/actions.ts b/src/stores/questions/actions.ts index f26e5b3d..c59e00db 100644 --- a/src/stores/questions/actions.ts +++ b/src/stores/questions/actions.ts @@ -297,7 +297,6 @@ export const uploadQuestionImage = async ( if (!question || !quizQid) return; try { - console.log(question.quizId) const response = await quizApi.addImages(question.quizId, blob); const values = Object.values(response); @@ -387,16 +386,13 @@ 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; } diff --git a/src/stores/quizes/actions.ts b/src/stores/quizes/actions.ts index 625fc12d..e0367bfd 100644 --- a/src/stores/quizes/actions.ts +++ b/src/stores/quizes/actions.ts @@ -179,7 +179,6 @@ export const deleteQuiz = async (quizId: string) => requestQueue.enqueue(async ( export const updateRootContentId = (quizId: string, id:string) => updateQuiz( quizId, quiz => { - console.log("Я изменение статуса корня проекта дерева, меняю на ", id) quiz.config.haveRoot = id }, ); diff --git a/src/stores/uiTools/actions.ts b/src/stores/uiTools/actions.ts index 03c2a534..ab1bedee 100644 --- a/src/stores/uiTools/actions.ts +++ b/src/stores/uiTools/actions.ts @@ -31,4 +31,9 @@ export const updateEditSomeQuestion = (contentId?: string) => { }; -export const updateOpenedModalSettingsId = (id?: string) => useUiTools.setState({ openedModalSettingsId: id ? id : null }); \ No newline at end of file +export const updateOpenedModalSettingsId = (id?: string) => useUiTools.setState({ openedModalSettingsId: id ? id : null }); + + +export const updateCanCreatePublic = (can: boolean) => useUiTools.setState({ canCreatePublic: can }); + +export const updateModalInfoWhyCantCreate = (can: boolean) => useUiTools.setState({ openModalInfoWhyCantCreate: can }); \ No newline at end of file diff --git a/src/stores/uiTools/store.ts b/src/stores/uiTools/store.ts index 2a102999..92e0d173 100644 --- a/src/stores/uiTools/store.ts +++ b/src/stores/uiTools/store.ts @@ -8,7 +8,15 @@ export type UiTools = { openBranchingPanel: boolean; desireToOpenABranchingModal: string | null; editSomeQuestion: string | null; + canCreatePublic: boolean; + whyCantCreatePublic: Record//ид вопроса и список претензий к нему + openModalInfoWhyCantCreate: boolean; }; +export type WhyCantCreatePublic = { + name: string; + problems: string[] + +} const initialState: UiTools = { openedModalSettingsId: null as null, @@ -16,6 +24,9 @@ const initialState: UiTools = { openBranchingPanel: false, desireToOpenABranchingModal: null as null, editSomeQuestion: null as null, + canCreatePublic: false, + whyCantCreatePublic: {}, + openModalInfoWhyCantCreate: false }; export const useUiTools = create()( diff --git a/src/stores/user.ts b/src/stores/user.ts index a6e5ad16..3c354187 100644 --- a/src/stores/user.ts +++ b/src/stores/user.ts @@ -1,4 +1,4 @@ -import { User } from "@frontend/kitui"; +import { User, UserAccount } from "@frontend/kitui"; import { produce } from "immer"; import { create } from "zustand"; import { createJSONStorage, devtools, persist } from "zustand/middleware"; @@ -6,12 +6,13 @@ import { createJSONStorage, devtools, persist } from "zustand/middleware"; interface UserStore { userId: string | null; user: User | null; - // userAccount: UserAccount | null; + userAccount: UserAccount | null; } const initialState: UserStore = { userId: null, user: null, + userAccount: null, }; export const useUserStore = create()( @@ -19,12 +20,11 @@ export const useUserStore = create()( devtools((set, get) => initialState, { name: "User", enabled: process.env.NODE_ENV === "development", - trace: true, + trace: process.env.NODE_ENV === "development", }), { version: 2, name: "user", - storage: createJSONStorage(() => localStorage), partialize: (state) => ({ userId: state.userId, user: state.user, @@ -46,3 +46,5 @@ export const setUser = (user: User) => ); export const clearUserData = () => useUserStore.setState({ ...initialState }); + +export const setUserAccount = (userAccount: UserAccount) => useUserStore.setState({ userAccount }); diff --git a/src/ui_kit/CustomTextField.tsx b/src/ui_kit/CustomTextField.tsx index b04df3b4..2b9c041e 100755 --- a/src/ui_kit/CustomTextField.tsx +++ b/src/ui_kit/CustomTextField.tsx @@ -1,7 +1,7 @@ -import { FormControl, TextField, useTheme, SxProps, Theme } from "@mui/material"; - +import React, { useState } from "react"; +import { Box, FormControl, TextField, Typography, useTheme } from "@mui/material"; import type { ChangeEvent, KeyboardEvent, FocusEvent } from "react"; -import type { InputProps } from "@mui/material"; +import type { InputProps, SxProps, Theme } from "@mui/material"; interface CustomTextFieldProps { placeholder: string; @@ -11,6 +11,7 @@ interface CustomTextFieldProps { onKeyDown?: (event: KeyboardEvent) => void; onBlur?: (event: FocusEvent) => void; text?: string; + maxLength?: number; sx?: SxProps; InputProps?: Partial; } @@ -18,28 +19,54 @@ interface CustomTextFieldProps { export default function CustomTextField({ placeholder, value, - text, - sx, - error, onChange, onKeyDown, onBlur, + text, + sx, + error, InputProps, + maxLength = 200, }: CustomTextFieldProps) { const theme = useTheme(); + const [inputValue, setInputValue] = useState(value || text || ""); + const [isInputActive, setIsInputActive] = useState(false); + + const handleInputChange = (event: React.ChangeEvent) => { + const inputValue = event.target.value; + setInputValue(inputValue); + + if (onChange) { + onChange(event); + } + }; + + const handleInputFocus = () => { + setIsInputActive(true); + }; + + const handleInputBlur = (event: React.FocusEvent) => { + setIsInputActive(false); + + if (onBlur) { + onBlur(event); + } + }; + return ( + {isInputActive && inputValue.length >= maxLength - 7 && ( + + {inputValue.length} + / + {maxLength} + + )} ); } diff --git a/src/ui_kit/Modal/CropModal.tsx b/src/ui_kit/Modal/CropModal.tsx index 4837f667..44b36023 100644 --- a/src/ui_kit/Modal/CropModal.tsx +++ b/src/ui_kit/Modal/CropModal.tsx @@ -18,6 +18,7 @@ import { FC, useEffect, useMemo, useRef, useState } from "react"; import ReactCrop, { PercentCrop, PixelCrop } from "react-image-crop"; import "react-image-crop/dist/ReactCrop.css"; import { getCroppedImageBlob, getDarkenedAndResizedImageBlob, getRotatedImageBlob } from "./utils/imageManipulation"; +import { isImageBlobAGifFile } from "../../utils/isImageBlobAGifFile"; const styleSlider: SxProps = { @@ -324,6 +325,9 @@ export function useCropModalState(initialOpenState = false) { image = await response.blob(); } + const isGif = await isImageBlobAGifFile(image); + if (isGif) return; + setCropModalImageBlob(image); setOriginalImageUrl(originalImageUrl); setOpened(true); diff --git a/src/ui_kit/ProblemIcon.tsx b/src/ui_kit/ProblemIcon.tsx new file mode 100644 index 00000000..39c6b9d1 --- /dev/null +++ b/src/ui_kit/ProblemIcon.tsx @@ -0,0 +1,23 @@ + +import Info from "@icons/Info"; + +interface Props { + blink: boolean; + onClick: (a: boolean) => void; +} +export const ProblemIcon = ({ blink, onClick }: Props) => { + + return ( + + ) +} \ No newline at end of file diff --git a/src/ui_kit/switchStepPages.tsx b/src/ui_kit/switchStepPages.tsx index b89b755a..35aad78e 100755 --- a/src/ui_kit/switchStepPages.tsx +++ b/src/ui_kit/switchStepPages.tsx @@ -24,6 +24,7 @@ export default function SwitchStepPages({ quizStartPageType, quizResults, }: Props) { + console.log("Выбор текущей странички") switch (activeStep) { case 0: { if (!quizType) return ; diff --git a/src/utils/isImageBlobAGifFile.ts b/src/utils/isImageBlobAGifFile.ts new file mode 100644 index 00000000..58c72cca --- /dev/null +++ b/src/utils/isImageBlobAGifFile.ts @@ -0,0 +1,15 @@ +const gifSignature = [0x47, 0x49, 0x46, 0x38]; + +export async function isImageBlobAGifFile(blob: Blob) { + const arrayBuffer = await blob.arrayBuffer(); + const uint8Array = new Uint8Array(arrayBuffer); + + if ( + uint8Array[0] === gifSignature[0] + && uint8Array[1] === gifSignature[1] + && uint8Array[2] === gifSignature[2] + && uint8Array[3] === gifSignature[3] + ) return true; + + return false; +} diff --git a/yarn.lock b/yarn.lock index 0372fc24..5c6fbdc9 100755 --- a/yarn.lock +++ b/yarn.lock @@ -1407,10 +1407,10 @@ resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz" integrity sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A== -"@frontend/kitui@^1.0.54": - version "1.0.54" - resolved "https://penahub.gitlab.yandexcloud.net/api/v4/projects/21/packages/npm/@frontend/kitui/-/@frontend/kitui-1.0.54.tgz#0235d5a8effb9b92351471c3c7775f28cb2839f6" - integrity sha1-AjXVqO/7m5I1FHHDx3dfKMsoOfY= +"@frontend/kitui@^1.0.55": + version "1.0.55" + resolved "https://penahub.gitlab.yandexcloud.net/api/v4/projects/21/packages/npm/@frontend/kitui/-/@frontend/kitui-1.0.55.tgz#6e02f80b2c13828142ffeacaf9704e50e54324d0" + integrity sha1-bgL4CywTgoFC/+rK+XBOUOVDJNA= dependencies: immer "^10.0.2" reconnecting-eventsource "^1.6.2"