diff --git a/src/App.tsx b/src/App.tsx index 2b2460fe..665e8d46 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -23,7 +23,7 @@ import { ResultSettings } from "./pages/ResultPage/ResultSettings"; import MyQuizzesFull from "./pages/createQuize/MyQuizzesFull"; import Main from "./pages/main"; import EditPage from "./pages/startPage/EditPage"; -import Tariffs from "./pages/Tariffs/Tariffs"; +import { Tariffs } from "./pages/Tariffs/Tariffs"; import { clearAuthToken, getMessageFromFetchError, @@ -101,20 +101,27 @@ export function useUserAccountFetcher({ dayjs.locale("ru"); const routeslink = [ - { path: "/list", page: , header: false, sidebar: false }, { - path: "/questions/:quizId", - page: , + path: "/tariffs", + page: , + header: true, + sidebar: false, + footer: false, + }, + { + path: "/edit", + page: , header: true, sidebar: true, + footer: true, + }, + { + path: "/design", + page: , + header: true, + sidebar: true, + footer: true, }, - { path: "/contacts", page: , header: true, sidebar: true }, - { path: "/result", page: , header: true, sidebar: true }, - { path: "/settings", page: , header: true, sidebar: true }, - { path: "/tariffs", page: , header: true, sidebar: false }, - { path: "/edit", page: , header: true, sidebar: true }, - { path: "/view", page: , header: false, sidebar: false }, - { path: "/design", page: , header: true, sidebar: true }, ] as const; export default function App() { @@ -190,13 +197,20 @@ export default function App() { } /> + } /> + } /> }> {routeslink.map((e, i) => ( +
} /> ))} diff --git a/src/pages/DesignPage/DesignPage.tsx b/src/pages/DesignPage/DesignPage.tsx index d35b5c51..8940a67c 100644 --- a/src/pages/DesignPage/DesignPage.tsx +++ b/src/pages/DesignPage/DesignPage.tsx @@ -25,19 +25,6 @@ import QuizPreview from "@ui_kit/QuizPreview/QuizPreview"; export const DesignPage = () => { const quiz = useCurrentQuiz(); const { editQuizId } = useQuizStore(); - - useEffect(() => { - const getData = async () => { - const quizes = await quizApi.getList(); - setQuizes(quizes); - if (editQuizId) { - const questions = await questionApi.getList({ quiz_id: editQuizId }); - setQuestions(questions); - } - }; - getData(); - }, []); - const { showConfirmLeaveModal } = useUiTools(); const theme = useTheme(); const navigate = useNavigate(); @@ -82,13 +69,13 @@ export const DesignPage = () => { ); return ( <> -
+ {/*
*/} - {isMobile ? ( - - ) : ( - - )} + {/*{isMobile ? (*/} + {/* */} + {/*) : (*/} + {/* */} + {/*)}*/} {createPortal(, document.body)} diff --git a/src/pages/Tariffs/Tariffs.tsx b/src/pages/Tariffs/Tariffs.tsx index b2e630dd..ff04d425 100644 --- a/src/pages/Tariffs/Tariffs.tsx +++ b/src/pages/Tariffs/Tariffs.tsx @@ -4,13 +4,13 @@ import { useEffect, useState } from "react"; import type { GetTariffsResponse } from "@model/tariff"; import { - Box, - Button, - Modal, - Paper, - Typography, - useMediaQuery, - useTheme, + Box, + Button, + Modal, + Paper, + Typography, + useMediaQuery, + useTheme, } from "@mui/material"; import { enqueueSnackbar } from "notistack"; import { Tariff, getMessageFromFetchError } from "@frontend/kitui"; @@ -18,194 +18,203 @@ import { withErrorBoundary } from "react-error-boundary"; import { createTariffElements } from "./tariffsUtils/createTariffElements"; function TariffPage() { - const theme = useTheme(); - const isTablet = useMediaQuery(theme.breakpoints.down(1000)); - // const location = useLocation(); - const navigate = useNavigate(); + const theme = useTheme(); + const isTablet = useMediaQuery(theme.breakpoints.down(1000)); + const location = useLocation(); + const navigate = useNavigate(); - const [tariffs, setTariffs] = useState(); - const [user, setUser] = useState(); - const [discounts, setDiscounts] = useState(); - const [cartTariffMap, setCartTariffMap] = useState(); - const [openModal, setOpenModal] = useState({}); + const [tariffs, setTariffs] = useState(); + const [user, setUser] = useState(); + const [discounts, setDiscounts] = useState(); + const [cartTariffMap, setCartTariffMap] = useState(); + const [openModal, setOpenModal] = useState({}); - useEffect(() => { - const get = async () => { - const user = await makeRequest({ - method: "GET", - url: "https://squiz.pena.digital/customer/account", - }); - const tariffs = await makeRequest({ - method: "GET", - url: "https://squiz.pena.digital/strator/tariff?page=1&limit=100", - }); - const discounts = await makeRequest({ - method: "GET", - url: "https://squiz.pena.digital/price/discounts", - }); - setUser(user); - setTariffs(tariffs); - setDiscounts(discounts.Discounts); - }; - get(); - }, []); - - if (!user || !tariffs || !discounts) return ; - - console.log("user ", user); - console.log("tariffs ", tariffs); - console.log("discounts ", discounts); - - const openModalHC = (tariffInfo: any) => setOpenModal(tariffInfo); - const tryBuy = async ({ id, price }: { id: string; price: number }) => { - openModalHC({}); - //Если в корзине что-то было - выкладываем содержимое и запоминаем чо там лежало - if (user.cart.length > 0) { - outCart(user.cart); - } - //Если нам хватает денежек - покупаем тариф - if (price <= user.wallet.cash) { - try { - await makeRequest({ - method: "POST", - url: "https://suiz.pena.digital/customer/cart/pay", - }); - } catch (e) { - enqueueSnackbar("Произошла ошибка. Попробуйте позже"); - } - //Развращаем товары в корзину - inCart(); - } else { - //Деняк не хватило - // history.pushState({}, null, "https://hub.pena.digital/wallet?action=squizpay"); - var link = document.createElement('a'); - link.href = `https://hub.pena.digital/payment?action=squizpay&dif=${(price - user.wallet) * 100}` - document.body.appendChild(link); - link.click(); - } + useEffect(() => { + const get = async () => { + const user = await makeRequest({ + method: "GET", + url: "https://squiz.pena.digital/customer/account", + }); + const tariffs = await makeRequest({ + method: "GET", + url: "https://squiz.pena.digital/strator/tariff?page=1&limit=100", + }); + const discounts = await makeRequest({ + method: "GET", + url: "https://squiz.pena.digital/price/discounts", + }); + setUser(user); + setTariffs(tariffs); + setDiscounts(discounts.Discounts); }; + get(); + }, []); - const purchasesAmount = user?.wallet.purchasesAmount ?? 0; - const isUserNko = user?.status === "nko"; - const filteredTariffs = tariffs.tariffs.filter((tariff) => { - return ( - tariff.privileges[0].serviceKey === "squiz" && - !tariff.isDeleted && - !tariff.isCustom - ); + if (!user || !tariffs || !discounts) return ; + + console.log("user ", user); + console.log("tariffs ", tariffs); + console.log("discounts ", discounts); + + const openModalHC = (tariffInfo: any) => setOpenModal(tariffInfo); + const tryBuy = async ({ id, price }: { id: string; price: number }) => { + openModalHC({}); + //Если в корзине что-то было - выкладываем содержимое и запоминаем чо там лежало + if (user.cart.length > 0) { + outCart(user.cart); + } + //Добавляем желаемый тариф в корзину + await makeRequest({ + method: "PATCH", + url: `https://hub.pena.digital/customer/cart?id=${id}`, }); + //Если нам хватает денежек - покупаем тариф + if (price <= user.wallet.cash) { + try { + await makeRequest({ + method: "POST", + url: "https://suiz.pena.digital/customer/cart/pay", + }); + } catch (e) { + enqueueSnackbar("Произошла ошибка. Попробуйте позже"); + } + //Развращаем товары в корзину + inCart(); + } else { + //Деняк не хватило + // history.pushState({}, null, "https://hub.pena.digital/wallet?action=squizpay"); + var link = document.createElement("a"); + link.href = `https://hub.pena.digital/payment?action=squizpay&dif=${ + (price - Number(user.wallet.cash)) * 100 + }`; + document.body.appendChild(link); + // link.click(); + } + }; + + const purchasesAmount = user?.wallet.purchasesAmount ?? 0; + const isUserNko = user?.status === "nko"; + const filteredTariffs = tariffs.tariffs.filter((tariff) => { return ( - <> - - {createTariffElements( - filteredTariffs, - true, - user, - discounts, - openModalHC, - )} - - 0} - onClose={() => setOpenModal({})} - > - - - Вы подтверждаете платёж в сумму {openModal.price} ₽ - - - - - + tariff.privileges[0].serviceKey === "squiz" && + !tariff.isDeleted && + !tariff.isCustom ); + }); + + return ( + <> + + {createTariffElements( + filteredTariffs, + true, + user, + discounts, + openModalHC, + )} + + 0} + onClose={() => setOpenModal({})} + > + + + Вы подтверждаете платёж в сумму {openModal.price} ₽ + + + + + + ); } -export default withErrorBoundary(TariffPage, { - fallback: ( - - Ошибка загрузки тарифов - - ), - onError: () => { }, +export const Tariffs = withErrorBoundary(TariffPage, { + fallback: ( + + Ошибка загрузки тарифов + + ), + onError: () => {}, }); const LoadingPage = () => ( - - - {"Подождите, пожалуйста, идёт загрузка :)"} - - + + + {"Подождите, пожалуйста, идёт загрузка :)"} + + ); -const inCart = () => { - let saveCart = JSON.parse(localStorage.getItem("saveCart") || "[]"); - saveCart.forEach(async (id: string) => { - try { - await makeRequest({ - method: "PATCH", - url: `https://hub.pena.digital/customer/cart?id=${id}`, - }); +export const inCart = () => { + let saveCart = JSON.parse(localStorage.getItem("saveCart") || "[]"); + saveCart.forEach(async (id: string) => { + try { + await makeRequest({ + method: "PATCH", + url: `https://hub.pena.digital/customer/cart?id=${id}`, + }); - let index = saveCart.indexOf("green"); - if (index !== -1) { - saveCart.splice(index, 1); - } - localStorage.setItem("saveCart", JSON.stringify(saveCart)); - } catch (e) { - console.log("Я не смог добавить тариф в корзину :( " + id); - } - }); + let index = saveCart.indexOf("green"); + if (index !== -1) { + saveCart.splice(index, 1); + } + localStorage.setItem("saveCart", JSON.stringify(saveCart)); + } catch (e) { + console.log("Я не смог добавить тариф в корзину :( " + id); + } + }); }; const outCart = (cart: string[]) => { - //Сделаем муторно и подольше, зато при прерывании сессии данные потеряются минимально - cart.forEach(async (id: string) => { - try { - await makeRequest({ - method: "DELETE", - url: `https://suiz.pena.digital/customer/cart?id=${id}`, - }); - let saveCart = JSON.parse(localStorage.getItem("saveCart") || "[]"); - saveCart = saveCart.push(id); - localStorage.setItem("saveCart", JSON.stringify(saveCart)); - } catch (e) { - console.log("Я не смог удалить из корзины тариф :("); - } - }); + //Сделаем муторно и подольше, зато при прерывании сессии данные потеряются минимально + cart.forEach(async (id: string) => { + try { + await makeRequest({ + method: "DELETE", + url: `https://suiz.pena.digital/customer/cart?id=${id}`, + }); + let saveCart = JSON.parse(localStorage.getItem("saveCart") || "[]"); + saveCart = saveCart.push(id); + localStorage.setItem("saveCart", JSON.stringify(saveCart)); + } catch (e) { + console.log("Я не смог удалить из корзины тариф :("); + } + }); }; diff --git a/src/pages/createQuize/MyQuizzesFull.tsx b/src/pages/createQuize/MyQuizzesFull.tsx index b0f15fe1..44c2099d 100644 --- a/src/pages/createQuize/MyQuizzesFull.tsx +++ b/src/pages/createQuize/MyQuizzesFull.tsx @@ -15,6 +15,7 @@ import { useNavigate } from "react-router-dom"; import { resetEditConfig } from "@root/quizes/actions"; import FirstQuiz from "./FirstQuiz"; import QuizCard from "./QuizCard"; +import HeaderFull from "@ui_kit/Header/HeaderFull"; interface Props { outerContainerSx?: SxProps; @@ -32,6 +33,7 @@ export default function MyQuizzesFull({ return ( <> + {quizes.length === 0 ? ( ) : ( diff --git a/src/pages/createQuize/QuizCard.tsx b/src/pages/createQuize/QuizCard.tsx index a2318c1b..32e7c2ff 100755 --- a/src/pages/createQuize/QuizCard.tsx +++ b/src/pages/createQuize/QuizCard.tsx @@ -1,4 +1,4 @@ -import { useState, useRef } from "react"; +import { useState, useRef, useLayoutEffect } from "react"; import ChartIcon from "@icons/ChartIcon"; import LinkIcon from "@icons/LinkIcon"; import PencilIcon from "@icons/PencilIcon"; @@ -15,6 +15,9 @@ import { } from "@mui/material"; import { deleteQuiz, setEditQuizId } from "@root/quizes/actions"; import { useNavigate } from "react-router-dom"; +import { inCart } from "../../pages/Tariffs/Tariffs"; +import { makeRequest } from "@frontend/kitui"; +import { enqueueSnackbar } from "notistack"; interface Props { quiz: Quiz; @@ -42,6 +45,28 @@ export default function QuizCard({ const questionCount = useRef(quiz.questions_count.toString() || ""); + useLayoutEffect(() => { + const pay = async () => { + try { + await makeRequest({ + method: "POST", + url: "https://suiz.pena.digital/customer/cart/pay", + }); + inCart(); + } catch (e) { + enqueueSnackbar( + "Попробуйте снова купить тариф после зачисления средств", + ); + } + }; + const params = new URLSearchParams(window.location.search); + const fromSquiz = params.get("action"); + if (fromSquiz === "fromhub") { + window.history.replaceState(null, '', "/list") + pay(); + } + }, []); + return ( state.currentStep); + + useEffect(() => { + const getData = async () => { + const quizes = await quizApi.getList(); + setQuizes(quizes); + + if (editQuizId) { + const questions = await questionApi.getList({ quiz_id: editQuizId }); + + setQuestions(questions); + //Всегда должен существовать хоть 1 резулт - "line" + if ( + !questions?.find( + (q) => + (q.type === "result" && q.content.includes(':"line"')) || + q.content.includes(":'line'"), + ) + ) { + createResult(quiz?.backendId, "line"); + console.log("Я не нашёл линейный резулт и собираюсь создать новый"); + } + } + }; + getData(); + }, []); + const isMobile = useMediaQuery(theme.breakpoints.down(600)); + const isMobileSm = useMediaQuery(theme.breakpoints.down(370)); + const isBranchingLogic = useMediaQuery(theme.breakpoints.down(1100)); + const isLinkButton = useMediaQuery(theme.breakpoints.down(708)); + const [mobileSidebar, setMobileSidebar] = useState(false); + const [nextStep, setNextStep] = useState(0); + const [openBranchingPage, setOpenBranchingPage] = useState(false); + + const openBranchingPageHC = () => { + if (!openBranchingPage) { + deleteTimeoutedQuestions(questions, quiz); + } + setOpenBranchingPage((old) => !old); + }; + + if (!quizConfig) return <>; + + const isConditionMet = + [1].includes(currentStep) && quizConfig.type !== "form"; + + const changePage = (index: number) => { + if (currentStep === 2) { + setNextStep(index); + setShowConfirmLeaveModal(true); + + return; + } + + setCurrentStep(index); + }; return ( <> - {header ?
: } +
- {sidebar ? : <>} + {sidebar ? ( + <> + {isMobile ? ( + + ) : ( + + )} + + ) : ( + <> + )} - {page} + + {page} + + + {footer && ( + + {isConditionMet && + (isBranchingLogic ? ( + + ) : ( + + ))} + {/* Кнопка тестового просмотра */} + + {/* Кнопка отозвать */} + + {/* Ссылка */} + {quiz?.status === "start" && + (!isLinkButton ? ( + + https://hbpn.link/{quiz.qid} + + ) : ( + + + + ))} + {/* Маленькая кнопка ссылки */} + {isMobile && quiz?.status === "start" && ( + + + + )} + + )} diff --git a/src/pages/startPage/EditPage.tsx b/src/pages/startPage/EditPage.tsx index ff8649ca..3b4a15c8 100755 --- a/src/pages/startPage/EditPage.tsx +++ b/src/pages/startPage/EditPage.tsx @@ -41,65 +41,22 @@ import { AnyTypedQuizQuestion } from "@model/questionTypes/shared"; import { ModalInfoWhyCantCreate } from "./ModalInfoWhyCantCreate"; import { ConfirmLeaveModal } from "./ConfirmLeaveModal"; import { checkQuestionHint } from "@utils/checkQuestionHint"; -import { deleteTimeoutedQuestions } from "@utils/deleteTimeoutedQuestions"; -import { toggleQuizPreview } from "@root/quizPreview"; -import { LinkSimple } from "@icons/LinkSimple"; -import { SmallSwitchQuestionListGraph } from "@ui_kit/Toolbars/SmallSwitchQuestionListGraph"; -import { PanelSwitchQuestionListGraph } from "@ui_kit/Toolbars/PanelSwitchQuestionListGraph"; -import { ButtonTestPublication } from "@ui_kit/Toolbars/ButtonTestPublication"; -import { ButtonRecallQuiz } from "@ui_kit/Toolbars/ButtonRecallQuiz"; export default function EditPage() { const quiz = useCurrentQuiz(); const { editQuizId } = useQuizStore(); const { questions } = useQuestionsStore(); console.log(questions); - - useEffect(() => { - const getData = async () => { - const quizes = await quizApi.getList(); - setQuizes(quizes); - - if (editQuizId) { - const questions = await questionApi.getList({ quiz_id: editQuizId }); - - setQuestions(questions); - //Всегда должен существовать хоть 1 резулт - "line" - if ( - !questions?.find( - (q) => - (q.type === "result" && q.content.includes(':"line"')) || - q.content.includes(":'line'"), - ) - ) { - createResult(quiz?.backendId, "line"); - console.log("Я не нашёл линейный резулт и собираюсь создать новый"); - } - } - }; - getData(); - }, []); - const { whyCantCreatePublic, showConfirmLeaveModal } = useUiTools(); const theme = useTheme(); const navigate = useNavigate(); const currentStep = useQuizStore((state) => state.currentStep); const isBranchingLogic = useMediaQuery(theme.breakpoints.down(1100)); const isMobile = useMediaQuery(theme.breakpoints.down(660)); - const isLinkButton = useMediaQuery(theme.breakpoints.down(708)); - const isMobileSm = useMediaQuery(theme.breakpoints.down(370)); - const [mobileSidebar, setMobileSidebar] = useState(false); const [nextStep, setNextStep] = useState(0); const quizConfig = quiz?.config; const [openBranchingPage, setOpenBranchingPage] = useState(false); - const openBranchingPageHC = () => { - if (!openBranchingPage) { - deleteTimeoutedQuestions(questions, quiz); - } - setOpenBranchingPage((old) => !old); - }; - useEffect(() => { if (editQuizId === null) navigate("/list"); }, [navigate, editQuizId]); @@ -144,33 +101,14 @@ export default function EditPage() { const isConditionMet = [1].includes(currentStep) && quizConfig.type !== "form"; - const changePage = (index: number) => { - if (currentStep === 2) { - setNextStep(index); - setShowConfirmLeaveModal(true); - - return; - } - - setCurrentStep(index); - }; - return ( <> -
- - {isMobile ? ( - - ) : ( - - )} - )} - - - {isConditionMet && - (isBranchingLogic ? ( - - ) : ( - - ))} - {/* Кнопка тестового просмотра */} - - {/* Кнопка отозвать */} - - {/* Ссылка */} - {quiz?.status === "start" && - (!isLinkButton ? ( - - https://hbpn.link/{quiz.qid} - - ) : ( - - - - ))} - {/* Маленькая кнопка ссылки */} - {isMobile && quiz?.status === "start" && ( - - - - )} - diff --git a/src/pages/startPage/Header.tsx b/src/pages/startPage/Header.tsx index 4789ba97..6100d001 100644 --- a/src/pages/startPage/Header.tsx +++ b/src/pages/startPage/Header.tsx @@ -80,12 +80,12 @@ export const Header = ({ setMobileSidebar }: HeaderProps) => { - updateQuiz(quiz.id, (quiz) => { - quiz.name = e.target.value; - }) - } + // value={quiz.name} + // onChange={(e) => + // updateQuiz(quiz.id, (quiz) => { + // quiz.name = e.target.value; + // }) + // } fullWidth id="project-name" placeholder="Название проекта окно"